home *** CD-ROM | disk | FTP | other *** search
/ CD World Haziran 1997 / CD World Haziran 1997.iso / Programlama ve Gelistirme / DTime / _SETUP.1 / Datetime.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-04  |  101.9 KB  |  4,198 lines

  1. /*
  2. Module : DATETIME.H
  3. Purpose: Implementation for a number of Date / Time classes
  4. Created: PJN / DATE/1 / 05-05-1995
  5. History: None
  6.  
  7. Copyright (c) 1995 by PJ Naughter.  
  8. All rights reserved.
  9.  
  10. */
  11.  
  12. /////////////////////////////////  Includes  //////////////////////////////////
  13. #include "stdafx.h"
  14. #include "limits.h"
  15. #include "time.h"
  16. #include "stdlib.h"
  17. #include "math.h"                                      
  18. #include "float.h"
  19. #include "datetime.h"
  20. #include "resource.h"
  21.  
  22.  
  23.  
  24. //////////////////////////////////  Macros  ///////////////////////////////////
  25. IMPLEMENT_SERIAL(CDate, CObject, VERSIONABLE_SCHEMA|1)
  26. IMPLEMENT_SERIAL(CLTimeSpan, CObject, VERSIONABLE_SCHEMA|1)
  27. IMPLEMENT_SERIAL(CLTimeOfDay, CObject, VERSIONABLE_SCHEMA|1)
  28. IMPLEMENT_SERIAL(CLDate, CObject, VERSIONABLE_SCHEMA|1)
  29.  
  30.  
  31.  
  32. #ifdef _DEBUG
  33. #undef THIS_FILE
  34. static char BASED_CODE THIS_FILE[] = __FILE__;
  35. #define new DEBUG_NEW
  36. #endif
  37.  
  38.  
  39. ////////////////////////////////// Locals /////////////////////////////////////
  40. LONG lfloor(LONG a, LONG b);
  41. void SetFebLength(BOOL bIsLeap);
  42. void ResetFebLength();
  43. long WeekOfDayModulo(long x, long y);
  44.  
  45.  
  46.  
  47. ////////////////////////////////// Statics ////////////////////////////////////
  48.  
  49. BOOL CDate::sm_bDoAsserts       = TRUE;
  50. LONG CDate::sm_lEndJulianYear  = 1582;
  51. WORD CDate::sm_wEndJulianMonth = 10;
  52. WORD CDate::sm_wEndJulianDay   = 4;
  53. LONG CDate::sm_lBeginGregYear  = 1582;
  54. WORD CDate::sm_wBeginGregMonth = 10; 
  55. WORD CDate::sm_wBeginGregDay   = 15;
  56. CString CDate::sm_sDefaultFormat = _T("%d/%m/%Y");
  57.  
  58. BOOL CLTimeSpan::sm_bDoAsserts  = TRUE;
  59. CString CLTimeSpan::sm_sDefaultFormat = _T("%D %H:%M:%S");
  60. CString CLTimeSpan::sm_sDefaultFormatNOS = _T("%H:%M"); 
  61.  
  62. BOOL CLTimeOfDay::sm_bDoAsserts = TRUE;   
  63. CString CLTimeOfDay::sm_sDefaultFormat = _T("%H:%M:%S"); 
  64. CString CLTimeOfDay::sm_sDefaultFormatNOS = _T("%H:%M"); 
  65.  
  66. BOOL CLDate::sm_bDoAsserts      = TRUE;
  67. BOOL CLDate::sm_bIsDst          = TRUE;
  68.  
  69.  
  70.  
  71.  
  72. static const int DeltaTTable[187] =
  73.  {1240, 1150, 1060, 980, 910, 850, 790, 740, 700, 650,
  74.   620, 580, 550, 530, 500, 480, 460, 440, 420, 400, 
  75.   370, 350, 330, 310, 280, 260, 240, 220, 200, 180, 
  76.   160, 140, 130, 120, 110, 100,  90,  90,  90,  90, 
  77.    90,  90,  90,  90, 100, 100, 100, 100, 100, 110, 
  78.   110, 110, 110, 110, 110, 110, 110, 120, 120, 120,
  79.   120, 120, 130, 130, 130, 130, 140, 140, 140, 150,
  80.   150, 150, 150, 160, 160, 160, 160, 160, 170, 170,
  81.   170, 170, 170, 170, 170, 170, 160, 160, 150, 140,
  82.   137, 131, 127, 125, 125, 125, 125, 125, 125, 123,
  83.   120, 114, 106,  96,  86,  75,  66,  60,  57,  56, 
  84.    57,  59,  62,  65,  68,  71,  73,  75,  77,  78,
  85.    79,  75,  64,  54,  29,  16, -10, -27, -36, -47,
  86.   -54, -52, -55, -56, -58, -59, -62, -64, -61, -47,
  87.   -27,   0,  26,  54,  77, 105, 134, 160, 182, 202,
  88.   212, 224, 235, 239, 243, 240, 239, 239, 237, 240,
  89.   243, 253, 262, 273, 282, 291, 300, 307, 314, 322,
  90.   331, 340, 350, 365, 383, 402, 422, 445, 465, 485,
  91.   505, 522, 538, 549, 558, 569, 580};
  92.  
  93. static WORD MonthLength[14] =
  94.   {
  95.   0,  31, 28, 31, 30, 31, 30,
  96.   31, 31, 30, 31, 30, 31, 0};
  97.  
  98.  
  99.  
  100.  
  101. ////////////////////////////////// Implementation /////////////////////////////
  102.             
  103.  
  104.  
  105. //Free Sub-Programs
  106.  
  107. long WeekOfDayModulo(long x, long y)
  108. {
  109.   if (x >= 0)
  110.     return x % y;
  111.   else
  112.   {
  113.     return (y - labs(x % y)) % y;
  114.   }
  115. }
  116.  
  117.  
  118. void SetFebLength(BOOL bIsLeap)
  119. {
  120.   MonthLength[2] = (WORD) (28 + bIsLeap);
  121. }
  122.  
  123. void ResetFebLength()
  124. {
  125.   MonthLength[2] = 28;
  126. };
  127.  
  128. LONG lfloor(LONG a, LONG b)
  129. {
  130.   ASSERT(b > 0);
  131.   return (a >= 0L ? a/b : (a%b == 0L) - 1 - labs(a)/b);
  132. }
  133.  
  134. void InitDTime()
  135. {
  136.   CDate::InitCalendarSettings();
  137.   CDate::GetDefaultFormat();
  138.   CLTimeSpan::GetDefaultFormat();
  139.   CLTimeOfDay::GetDefaultFormat();
  140. }
  141.  
  142.  
  143.  
  144. //CDate Implementation
  145.  
  146. CDate::CDate()
  147. {
  148.   Set();
  149. }
  150.  
  151. CDate::CDate(LONG Year, WORD Month, WORD Day)
  152.   Set(Year, Month, Day);
  153. }
  154.  
  155. CDate::CDate(const SYSTEMTIME& st)
  156. {
  157.   Set(st);
  158. }
  159.  
  160. CDate::CDate(LONG Year, WORD Month, WORD WeekOfMonth, WORD DayOfWeek)
  161. {
  162.   Set(Year, Month, WeekOfMonth, DayOfWeek);
  163. }
  164.  
  165. CDate::CDate(LONG Days, DateEpoch e)
  166. {
  167.   Set(Days, e);
  168. }
  169.  
  170. CDate::CDate(const CDate& d)
  171. {
  172.   m_lDays = d.m_lDays;
  173.   m_bValid = d.m_bValid;
  174.   m_bInGregCalendar = d.m_bInGregCalendar;
  175. }
  176.  
  177. CDate::CDate(const CTime& ctime)
  178. {
  179.   Set(ctime.GetTime()/86400, EPOCH_CTIME);
  180. }
  181.                                      
  182. CDate::CDate(const COleDateTime& oleTime)
  183. {
  184.   Set(oleTime);
  185. }                     
  186.  
  187. CDate& CDate::Set()
  188. {
  189.   m_lDays = 0;
  190.   m_bValid = FALSE;
  191.   m_bInGregCalendar = FALSE;
  192.   return *this;
  193. }
  194.  
  195. CDate& CDate::Set(LONG Year, WORD Month, WORD Day)
  196. {
  197.   //The following method has been taken from the magazine "Microsoft Systems Journal"
  198.   //I cannot find the copy again, so if anyone recognises the algorithm please let
  199.   //me know so I can credit the author.
  200.  
  201.   if (Month < JANUARY || Month > DECEMBER ||
  202.       Day > DaysInMonth(Month, IsLeap(Year)))
  203.   {
  204.     if (sm_bDoAsserts)
  205.       ASSERT(FALSE);
  206.     Set();
  207.     return *this;
  208.   }
  209.   
  210.   if (((Year > sm_lEndJulianYear) && (Year < sm_lBeginGregYear)) ||
  211.       ((Year == sm_lEndJulianYear) && ((Month > sm_wEndJulianMonth) && (Month < sm_wBeginGregMonth))) ||
  212.       ((Year == sm_lEndJulianYear) && (Month == sm_wEndJulianMonth) && (Day > sm_wEndJulianDay) && (Day < sm_wBeginGregDay)))
  213.   {
  214.     if (sm_bDoAsserts)
  215.       ASSERT(FALSE);
  216.     Set();
  217.     return *this;
  218.   }
  219.  
  220.   SetFebLength(IsLeap(Year));
  221.   m_lDays = (Year-1)*365 + lfloor(Year-1, 4L);
  222.   m_bInGregCalendar = InGregorianCalendar(Year, Month, Day);
  223.   if (m_bInGregCalendar)
  224.     m_lDays += lfloor(Year-1, 400L) - lfloor(Year-1, 100L);
  225.   while (--Month)
  226.     m_lDays += MonthLength[Month];
  227.   //m_lDays += Day - 577736L + 2000000000L - 2*(!m_bInGregCalendar);   //ensure all usable date values are positive
  228.   m_lDays += Day + 1999422264L - 2*(!m_bInGregCalendar);  
  229.  
  230.   ResetFebLength();
  231.  
  232.   m_bValid = TRUE;
  233.  
  234.   return *this;
  235. }
  236.  
  237. CDate& CDate::Set(LONG Year, WORD Month, WORD WeekOfMonth, WORD DayOfWeek)
  238. {
  239.   if (WeekOfMonth < 1 || WeekOfMonth > 5 || DayOfWeek < 1 && DayOfWeek > 7)
  240.   {
  241.     if (sm_bDoAsserts)
  242.       ASSERT(FALSE);
  243.     Set();
  244.     return *this;
  245.   }
  246.  
  247.   if (WeekOfMonth < 5)
  248.   {
  249.     CDate FirstMonth(Year, Month, 1);
  250.     if (!FirstMonth.IsValid())
  251.     {
  252.       if (sm_bDoAsserts)
  253.         ASSERT(FALSE);
  254.       Set();
  255.       return *this;
  256.     }
  257.     WORD dow = FirstMonth.GetDayOfWeek();
  258.     WORD Day = (WORD) (((DayOfWeek - dow + 7) % 7) + (7*(WeekOfMonth-1)) + 1);
  259.     Set(Year, Month, Day);
  260.   }
  261.   else  //5 means the last week of the month
  262.   {
  263.     WORD NewMonth = (WORD) (Month + 1);
  264.     LONG NewYear = Year;
  265.     if (NewMonth > DECEMBER)
  266.     {
  267.       NewMonth = 1;
  268.       ++NewYear;
  269.     }
  270.        
  271.     Set(NewYear, NewMonth, 1, DayOfWeek);
  272.     AddWeek(-1);
  273.   }
  274.  
  275.   return *this;
  276. }
  277.  
  278. CDate& CDate::Set(LONG Days, DateEpoch e)
  279. {
  280.   switch (e)
  281.   {
  282.     case EPOCH_GREG:
  283.     {
  284.       m_lDays = Days + 2000000000L;
  285.       break;
  286.     }
  287.     case EPOCH_JD:    
  288.     {
  289.       //m_lDays = Days - 2299161L + 2000000000L;  //-2299161 coresponds to the GDN of JD Epoch namely 1 January -4712 
  290.       m_lDays = Days + 1997700839L;
  291.       break;
  292.     }
  293.     case EPOCH_MJD:   
  294.     {
  295.       //m_lDays = Days + 100839L + 2000000000L;  //100839 coresponds to the GDN of MJD Epoch namely 17 November 1858 
  296.       m_lDays = Days + 2000100839L;
  297.       break;
  298.     }
  299.     case EPOCH_1900:
  300.     {
  301.       //m_lDays = Days + 115860L + 2000000000L;  //115860 corresponds to the GDN of 1 January 1900
  302.       m_lDays = Days + 2000115860L;
  303.       break;
  304.     }
  305.     case EPOCH_1950:
  306.     {
  307.       //m_lDays = Days + 134122L + 2000000000L;  //134122 corresponds to the GDN of 1 January 1950
  308.       m_lDays = Days + 2000134122L;
  309.       break;
  310.     }
  311.     case EPOCH_CTIME:
  312.     {
  313.       //m_lDays = Days + 141427L + 2000000000L;  //141427 corresponds to the GDN of 1 January 1970
  314.       m_lDays = Days + 2000141427L;
  315.       break;
  316.     }
  317.     case EPOCH_2000:  
  318.     {
  319.       //m_lDays = Days + 152384L + 2000000000L;  //152384 corresponds to the GDN of 1 January 2000
  320.       m_lDays = Days + 2000152384L;
  321.       break;
  322.     }
  323.     default: ASSERT(FALSE); //should not occur
  324.   }
  325.  
  326.   m_bValid = TRUE;
  327.     
  328.   //if (m_lDays - 2000000000L > 2146905911L)  //Largest valid GDN
  329.   if (m_lDays > 4146905911L)  //Largest valid GDN
  330.   {
  331.     if (sm_bDoAsserts)
  332.       ASSERT(FALSE);
  333.     Set();
  334.   }
  335.  
  336.   m_bInGregCalendar = *this > CDate(BeginGregorianYear(), BeginGregorianMonth(), BeginGregorianDay());
  337.  
  338.   return *this;
  339. }
  340.  
  341. CDate& CDate::Set(const SYSTEMTIME& st)
  342. {
  343.   Set(st.wYear, st.wMonth, st.wDay);
  344.   return *this;
  345. }
  346.  
  347. CDate& CDate::Set(const CTime& ctime)
  348. {
  349.   return Set(ctime.GetTime()/86400, EPOCH_CTIME);
  350. }
  351.       
  352. CDate& CDate::Set(const COleDateTime& oleTime)
  353. {
  354.   COleDateTime::DateTimeStatus dts(oleTime.GetStatus());
  355.   CDate rVal;
  356.   if (dts == COleDateTime::DateTimeStatus::valid)
  357.     Set((LONG) oleTime.GetYear(), (WORD) oleTime.GetMonth(), (WORD) oleTime.GetDay());
  358.   else
  359.     Set();
  360.   return *this;
  361. }                     
  362.  
  363. CDate CDate::CurrentDate()
  364. {   
  365.   SYSTEMTIME st;
  366.   ::GetLocalTime(&st);
  367.   return CDate(st);
  368. }
  369.  
  370. WORD CDate::CurrentMonth()
  371. {              
  372.   return CurrentDate().GetMonth();
  373. }
  374.  
  375. WORD CDate::CurrentDay()
  376. {
  377.   return CurrentDate().GetDay();
  378. }
  379.  
  380. LONG CDate::CurrentYear()
  381. {                               
  382.   return CurrentDate().GetYear();
  383. }
  384.  
  385. WORD CDate::CurrentDayOfWeek()
  386. {            
  387.   return CurrentDate().GetDayOfWeek();
  388. }
  389.  
  390. WORD CDate::GetBeginingDayOfWeek()
  391. {
  392.   WORD nDayOfWeek = MONDAY;
  393.   CString sBuf;
  394.   LPTSTR pszBuf = sBuf.GetBuffer(10);
  395.   int nBytes = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, pszBuf, 10);
  396.   ASSERT(nBytes);
  397.   sBuf.ReleaseBuffer();
  398.  
  399.   if (sBuf == _T("0"))
  400.     nDayOfWeek = MONDAY;
  401.   else if (sBuf == _T("1"))
  402.     nDayOfWeek = TUESDAY;
  403.   else if (sBuf == _T("2"))
  404.     nDayOfWeek = WEDNESDAY;
  405.   else if (sBuf == _T("3"))
  406.     nDayOfWeek = THURSDAY;
  407.   else if (sBuf == _T("4"))
  408.     nDayOfWeek = FRIDAY;
  409.   else if (sBuf == _T("5"))
  410.     nDayOfWeek = SATURDAY;
  411.   else if (sBuf == _T("6"))
  412.     nDayOfWeek = SUNDAY;
  413.   else
  414.     ASSERT(FALSE);
  415.  
  416.   return nDayOfWeek;
  417. }
  418.  
  419. BOOL CDate::SetEndJulianCalendar(LONG Year, WORD Month, WORD Day)
  420. {
  421.   //Update the static values in memory first
  422.   sm_wEndJulianDay = Day;
  423.   sm_wEndJulianMonth = Month;
  424.   sm_lEndJulianYear = Year;
  425.  
  426.   //Broadcast a message to all top level windows that we are about to change
  427.   //some internationl settings in the registry
  428.   SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, NULL); 
  429.  
  430.   //Settings are stored in the registry under the key HKEY_CURRENT_USER\Control Panel\DTime
  431.   HKEY hcpl;
  432.   BOOL bSuccess = TRUE;
  433.  
  434.   if (RegOpenKeyEx(HKEY_CURRENT_USER,
  435.                    _T("Control Panel"),
  436.                    0,
  437.                    KEY_WRITE,
  438.                    &hcpl) == ERROR_SUCCESS) 
  439.   {
  440.     HKEY happ;
  441.     DWORD dwDisp;
  442.     if (RegCreateKeyEx(hcpl, _T("DTime"), 0, _T(""), REG_OPTION_NON_VOLATILE,
  443.                        KEY_WRITE, NULL, &happ, &dwDisp) == ERROR_SUCCESS) 
  444.     {
  445.       // Set the day part of the end of Julian Calendar
  446.       DWORD dwDay = (DWORD) Day;
  447.       if (RegSetValueEx(happ, _T("JulianEndDay"), 0, REG_DWORD,
  448.                         (BYTE*)&dwDay, sizeof(DWORD)) != ERROR_SUCCESS)
  449.         bSuccess = FALSE;
  450.  
  451.       // Set the month part of the end of Julian Calendar
  452.       DWORD dwMonth = (DWORD) Month;
  453.       if (RegSetValueEx(happ, _T("JulianEndMonth"), 0, REG_DWORD,
  454.                     (BYTE*)&dwMonth, sizeof(DWORD)) != ERROR_SUCCESS)
  455.         bSuccess = FALSE;
  456.  
  457.       // Set the year part of the end of Julian Calendar
  458.       if (RegSetValueEx(happ, _T("JulianEndYear"),  0, REG_DWORD,
  459.                     (BYTE*)&Year, sizeof(LONG)) != ERROR_SUCCESS)
  460.         bSuccess = FALSE;
  461.  
  462.       // Finished with keys
  463.       RegCloseKey(happ);
  464.     }
  465.     else
  466.       bSuccess = FALSE;
  467.  
  468.     RegCloseKey(hcpl);
  469.   }
  470.   else
  471.     bSuccess = FALSE;
  472.  
  473.   return bSuccess;
  474. }
  475.  
  476. BOOL CDate::SetBeginGregorianCalendar(LONG Year, WORD Month, WORD Day)
  477. {
  478.   //Update the static values in memory first
  479.   sm_wBeginGregDay = Day;
  480.   sm_wBeginGregMonth = Month;
  481.   sm_lBeginGregYear = Year;
  482.  
  483.   //Broadcast a message to all top level windows that we are about to change
  484.   //some internationl settings in the registry
  485.   SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, NULL); 
  486.  
  487.   //Settings are stored in the registry under the key HKEY_CURRENT_USER\Control Panel\DTime
  488.   HKEY hcpl;
  489.   BOOL bSuccess = TRUE;
  490.  
  491.   if (RegOpenKeyEx(HKEY_CURRENT_USER,
  492.                    _T("Control Panel"),
  493.                    0,
  494.                    KEY_WRITE,
  495.                    &hcpl) == ERROR_SUCCESS) 
  496.   {
  497.     HKEY happ;
  498.     DWORD dwDisp;
  499.     if (RegCreateKeyEx(hcpl, _T("DTime"), 0, _T(""), REG_OPTION_NON_VOLATILE,
  500.                        KEY_WRITE, NULL, &happ, &dwDisp) == ERROR_SUCCESS) 
  501.     {
  502.       // Set the day part of the begin of the Gregorian Calendar
  503.       DWORD dwDay = (DWORD) Day;
  504.       if (RegSetValueEx(happ, _T("GregorianBeginDay"), 0, REG_DWORD,
  505.                         (BYTE*)&dwDay, sizeof(DWORD)) != ERROR_SUCCESS)
  506.         bSuccess = FALSE;
  507.  
  508.       // Set the month part of the begin of the Gregorian Calendar
  509.       DWORD dwMonth = (DWORD) Month;
  510.       if (RegSetValueEx(happ, _T("GregorianBeginMonth"), 0, REG_DWORD,
  511.                     (BYTE*)&dwMonth, sizeof(DWORD)) != ERROR_SUCCESS)
  512.         bSuccess = FALSE;
  513.  
  514.       // Set the year part of the begin of the Gregorian Calendar
  515.       if (RegSetValueEx(happ, _T("GregorianBeginYear"),  0, REG_DWORD,
  516.                     (BYTE*)&Year, sizeof(LONG)) != ERROR_SUCCESS)
  517.         bSuccess = FALSE;
  518.  
  519.       // Finished with keys
  520.       RegCloseKey(happ);
  521.     }
  522.     else
  523.       bSuccess = FALSE;
  524.  
  525.     RegCloseKey(hcpl);
  526.   }
  527.   else
  528.     bSuccess = FALSE;
  529.  
  530.   return bSuccess;
  531. }
  532.  
  533. void CDate::GetEndJulianCalendar(LONG& Year, WORD& Month, WORD& Day)
  534. {
  535.   Year  = sm_lEndJulianYear;
  536.   Month = sm_wEndJulianMonth;
  537.   Day   = sm_wEndJulianDay;
  538. }
  539.  
  540. void CDate::GetBeginGregorianCalendar(LONG& Year, WORD& Month, WORD& Day)
  541. {
  542.   Year  = sm_lBeginGregYear;
  543.   Month = sm_wBeginGregMonth;
  544.   Day   = sm_wBeginGregDay;
  545. }
  546.  
  547. BOOL CDate::InitCalendarSettings()
  548. {
  549.   BOOL bSuccess = TRUE;
  550.  
  551.   // Read the current state from the registry
  552.   // Try opening the registry key:
  553.   // HKEY_CURRENT_USER\Control Panel\DTime
  554.   HKEY hCPL;
  555.   if (RegOpenKeyEx(HKEY_CURRENT_USER,
  556.                    _T("Control Panel"),
  557.                    0,
  558.                    KEY_QUERY_VALUE,
  559.                    &hCPL) == ERROR_SUCCESS) 
  560.   {
  561.     HKEY hApp;
  562.     if (RegOpenKeyEx(hCPL,
  563.                      _T("DTime"),
  564.                      0,
  565.                      KEY_QUERY_VALUE,
  566.                      &hApp) == ERROR_SUCCESS) 
  567.     {
  568.       // Yes we are installed
  569.  
  570.       //the day part of the gregorian begin date
  571.       DWORD dwSize = sizeof(DWORD);
  572.       DWORD dwDay;
  573.       if (RegQueryValueEx(hApp, _T("GregorianBeginDay"), NULL,
  574.                       NULL, (BYTE*)&dwDay, &dwSize) != ERROR_SUCCESS)
  575.         bSuccess = FALSE;
  576.       else
  577.         sm_wBeginGregDay = (WORD) dwDay;
  578.  
  579.       //the month part of the gregorian begin date
  580.       dwSize = sizeof(DWORD);
  581.       DWORD dwMonth;
  582.       if (RegQueryValueEx(hApp, _T("GregorianBeginMonth"), NULL,
  583.                       NULL, (BYTE*)&dwMonth, &dwSize) != ERROR_SUCCESS)
  584.         bSuccess = FALSE;
  585.       else
  586.         sm_wBeginGregMonth = (WORD) dwMonth;
  587.  
  588.       //the year part of the gregorian begin date
  589.       dwSize = sizeof(LONG);
  590.       if (RegQueryValueEx(hApp, _T("GregorianBeginYear"), NULL,
  591.                       NULL, (BYTE*)&sm_lBeginGregYear, &dwSize) != ERROR_SUCCESS)
  592.         bSuccess = FALSE;
  593.  
  594.  
  595.       //the day part of the julian end date
  596.       dwSize = sizeof(DWORD);
  597.       if (RegQueryValueEx(hApp, _T("JulianEndDay"), NULL,
  598.                       NULL, (BYTE*)&dwDay, &dwSize) != ERROR_SUCCESS)
  599.         bSuccess = FALSE;
  600.       else
  601.         sm_wEndJulianDay = (WORD) dwDay;
  602.  
  603.       //the month part of the julian end date
  604.       dwSize = sizeof(DWORD);
  605.       if (RegQueryValueEx(hApp, _T("JulianEndMonth"), NULL,
  606.                       NULL, (BYTE*)&dwMonth, &dwSize) != ERROR_SUCCESS)
  607.         bSuccess = FALSE;
  608.       else
  609.         sm_wEndJulianMonth = (WORD) dwMonth;
  610.  
  611.       //the year part of the julian end date
  612.       dwSize = sizeof(LONG);
  613.       if (RegQueryValueEx(hApp, _T("JulianEndYear"), NULL,
  614.                       NULL, (BYTE*)&sm_lEndJulianYear, &dwSize) != ERROR_SUCCESS)
  615.         bSuccess = FALSE;
  616.  
  617.  
  618.       //Close the DTime Key 
  619.       RegCloseKey(hApp);
  620.     }
  621.     else
  622.       bSuccess = FALSE;
  623.  
  624.     //Close the Control Panel Registry key
  625.     RegCloseKey(hCPL);
  626.   }
  627.   else
  628.     bSuccess = FALSE;
  629.  
  630.   return bSuccess;
  631. }
  632.  
  633. LONG CDate::EndJulianYear()
  634. {
  635.   LONG Year;
  636.   WORD Month;
  637.   WORD Day;
  638.   GetEndJulianCalendar(Year, Month, Day);
  639.   return Year;
  640. }
  641.  
  642. WORD CDate::EndJulianMonth()
  643. {
  644.   LONG Year;
  645.   WORD Month;
  646.   WORD Day;
  647.   GetEndJulianCalendar(Year, Month, Day);
  648.   return Month;
  649. }
  650.  
  651. WORD CDate::EndJulianDay()
  652. {
  653.   LONG Year;
  654.   WORD Month;
  655.   WORD Day;
  656.   GetEndJulianCalendar(Year, Month, Day);
  657.   return Day;
  658. }
  659.  
  660. LONG CDate::BeginGregorianYear()
  661. {
  662.   LONG Year;
  663.   WORD Month;
  664.   WORD Day;
  665.   GetBeginGregorianCalendar(Year, Month, Day);
  666.   return Year;
  667. }
  668.  
  669. WORD CDate::BeginGregorianMonth()
  670. {
  671.   LONG Year;
  672.   WORD Month;
  673.   WORD Day;
  674.   GetBeginGregorianCalendar(Year, Month, Day);
  675.   return Month;
  676. }
  677.  
  678. WORD CDate::BeginGregorianDay()
  679. {
  680.   LONG Year;
  681.   WORD Month;
  682.   WORD Day;
  683.   GetBeginGregorianCalendar(Year, Month, Day);
  684.   return Day;
  685. }
  686.  
  687. BOOL CDate::InGregorianCalendar(LONG Year, WORD Month, WORD Day)
  688. {
  689.   if (Year == BeginGregorianYear())
  690.   {
  691.     if (Month == BeginGregorianMonth())
  692.       return (Day >= BeginGregorianDay());
  693.     else
  694.       return (Month > BeginGregorianMonth());
  695.   }
  696.   else
  697.     return (Year > BeginGregorianYear());
  698. }
  699.  
  700. BOOL CDate::InJulianCalendar(LONG Year, WORD Month, WORD Day)
  701. {
  702.   if (Year == EndJulianYear())
  703.   {
  704.     if (Month == EndJulianMonth())
  705.       return (Day < EndJulianDay());
  706.     else
  707.       return (Month < EndJulianMonth());
  708.   }
  709.   else
  710.     return (Year < EndJulianYear());
  711. }
  712.  
  713.  
  714. #ifdef _DEBUG
  715. BOOL CDate::SetDoConstructorAsserts(BOOL bDoAsserts)
  716. {
  717.   BOOL bOldDoAsserts = sm_bDoAsserts;
  718.   sm_bDoAsserts = bDoAsserts;
  719.   return bOldDoAsserts;
  720. }
  721. #endif
  722.  
  723. CString CDate::GetFullStringDayOfWeek(WORD DayOfWeek)
  724. {
  725.   CString rVal;
  726.   LPTSTR pszBuf = rVal.GetBuffer(100);
  727.   if (DayOfWeek > 0 && DayOfWeek <= 7)
  728.   {
  729.     int nChars;
  730.     switch (DayOfWeek)
  731.     {
  732.       case MONDAY:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME1, pszBuf, 100); break;
  733.       case TUESDAY:   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME2, pszBuf, 100); break;
  734.       case WEDNESDAY: nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME3, pszBuf, 100); break;
  735.       case THURSDAY:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME4, pszBuf, 100); break;
  736.       case FRIDAY:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME5, pszBuf, 100); break;
  737.       case SATURDAY:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME6, pszBuf, 100); break;
  738.       case SUNDAY:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME7, pszBuf, 100); break;
  739.       default: ASSERT(FALSE); break;
  740.     }
  741.     ASSERT(nChars);
  742.   }
  743.   else
  744.     ASSERT(FALSE);
  745.   rVal.ReleaseBuffer();
  746.   return rVal;
  747. }
  748.  
  749. CString CDate::GetAbrStringDayOfWeek(WORD DayOfWeek)
  750. {
  751.   CString rVal;
  752.   LPTSTR pszBuf = rVal.GetBuffer(100);
  753.   if (DayOfWeek > 0 && DayOfWeek <= 7)
  754.   {
  755.     int nChars;
  756.     switch (DayOfWeek)
  757.     {
  758.       case MONDAY:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1, pszBuf, 100); break;
  759.       case TUESDAY:   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME2, pszBuf, 100); break;
  760.       case WEDNESDAY: nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME3, pszBuf, 100); break;
  761.       case THURSDAY:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME4, pszBuf, 100); break;
  762.       case FRIDAY:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME5, pszBuf, 100); break;
  763.       case SATURDAY:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME6, pszBuf, 100); break;
  764.       case SUNDAY:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME7, pszBuf, 100); break;
  765.       default: ASSERT(FALSE); break;
  766.     }
  767.     ASSERT(nChars);
  768.   }
  769.   else
  770.     ASSERT(FALSE);
  771.   rVal.ReleaseBuffer();
  772.   return rVal;
  773. }
  774.  
  775. CString CDate::GetFullStringMonth(WORD Month)
  776. {
  777.   CString rVal;
  778.   LPTSTR pszBuf = rVal.GetBuffer(100);
  779.   if (Month > 0 && Month <= 12)
  780.   {
  781.     int nChars;
  782.     switch (Month)
  783.     {
  784.       case JANUARY:   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1, pszBuf, 100); break;
  785.       case FEBRUARY:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME2, pszBuf, 100); break;
  786.       case MARCH:     nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME3, pszBuf, 100); break;
  787.       case APRIL:     nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME4, pszBuf, 100); break;
  788.       case MAY:       nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME5, pszBuf, 100); break;
  789.       case JUNE:      nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME6, pszBuf, 100); break;
  790.       case JULY:      nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME7, pszBuf, 100); break;
  791.       case AUGUST:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME8, pszBuf, 100); break;
  792.       case SEPTEMBER: nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME9, pszBuf, 100); break;
  793.       case OCTOBER:   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME10, pszBuf, 100); break;
  794.       case NOVEMBER:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME11, pszBuf, 100); break;
  795.       case DECEMBER:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME12, pszBuf, 100); break;
  796.       default: ASSERT(FALSE); break;
  797.     }
  798.     ASSERT(nChars);
  799.   }
  800.   else
  801.     ASSERT(FALSE);
  802.   rVal.ReleaseBuffer();
  803.   return rVal;
  804. }
  805.  
  806. CString CDate::GetAbrStringMonth(WORD Month)
  807. {
  808.   CString rVal;
  809.   LPTSTR pszBuf = rVal.GetBuffer(100);
  810.   if (Month > 0 && Month <= 12)
  811.   {
  812.     int nChars;
  813.     switch (Month)
  814.     {
  815.       case JANUARY:   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME1, pszBuf, 100); break;
  816.       case FEBRUARY:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME2, pszBuf, 100); break;
  817.       case MARCH:     nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME3, pszBuf, 100); break;
  818.       case APRIL:     nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME4, pszBuf, 100); break;
  819.       case MAY:       nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME5, pszBuf, 100); break;
  820.       case JUNE:      nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME6, pszBuf, 100); break;
  821.       case JULY:      nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME7, pszBuf, 100); break;
  822.       case AUGUST:    nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME8, pszBuf, 100); break;
  823.       case SEPTEMBER: nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME9, pszBuf, 100); break;
  824.       case OCTOBER:   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME10, pszBuf, 100); break;
  825.       case NOVEMBER:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME11, pszBuf, 100); break;
  826.       case DECEMBER:  nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME12, pszBuf, 100); break;
  827.       default: ASSERT(FALSE); break;
  828.     }
  829.     ASSERT(nChars);
  830.   }
  831.   else
  832.     ASSERT(FALSE);
  833.   rVal.ReleaseBuffer();
  834.   return rVal;
  835. }
  836.  
  837. CDate CDate::FirstCurrentMonth()
  838. {
  839.   CDate c = CDate::CurrentDate();
  840.   return CDate(c.GetYear(), c.GetMonth(), 1); 
  841. }
  842.  
  843. CDate CDate::LastCurrentMonth()
  844. {
  845.   CDate c = CDate::CurrentDate();
  846.   return CDate(c.GetYear(), c.GetMonth(), c.DaysInMonth()); 
  847. }
  848.  
  849. CDate CDate::FirstCurrentYear()
  850. {
  851.   CDate c = CDate::CurrentDate();
  852.   return CDate(c.GetYear(), 1, 1); 
  853. }              
  854.  
  855. CDate CDate::LastCurrentYear()
  856. {
  857.   CDate c = CDate::CurrentDate();
  858.   return CDate(c.GetYear(), 12, CDate::DaysInMonth(12, c.IsLeap())); 
  859. }
  860.  
  861. CDate CDate::JDEpoch()
  862. {
  863.   return CDate(0, EPOCH_JD);
  864. }
  865.  
  866. CDate CDate::MJDEpoch()
  867. {
  868.   return CDate(0, EPOCH_MJD);
  869. }
  870.  
  871. CDate CDate::Epoch1900()
  872. {
  873.   return CDate(0, EPOCH_1900);
  874. }
  875.  
  876. CDate CDate::Epoch1950()
  877. {
  878.   return CDate(0, EPOCH_1950);
  879. }
  880.  
  881. CDate CDate::EpochCTime()
  882. {
  883.   return CDate(0, EPOCH_CTIME);
  884. }
  885.  
  886. CDate CDate::Epoch2000()
  887. {
  888.   return CDate(0, EPOCH_2000);
  889. }
  890.  
  891. CDate CDate::GregorianEpoch()
  892. {
  893.   return CDate(0, EPOCH_GREG);
  894. }                 
  895.  
  896. CDate CDate::NewYearsDay(LONG Year) 
  897. {
  898.   return CDate(Year, JANUARY, 1);
  899. }
  900.  
  901. CDate CDate::ValentinesDay(LONG Year) 
  902. {
  903.   return CDate(Year, FEBRUARY, 14);
  904. }
  905.  
  906. CDate CDate::AshWednesday(LONG Year)
  907. {                                      
  908.   return CDate::EasterSunday(Year) - 39L;    //Ash Wednesday occurs 39 days before Easter Sunday
  909. }
  910.  
  911. CDate CDate::StPatricksDay(LONG Year) 
  912. {
  913.   return CDate(Year, MARCH, 17);
  914. }
  915.  
  916. CDate CDate::GoodFriday(LONG Year)
  917.   return CDate::EasterSunday(Year) - 2L;     //Good Friday occurs 2 days before Easter Sunday
  918. }
  919.  
  920. CDate CDate::EasterSunday(LONG Year)
  921. {
  922.   //The following method has been taken from the book "Astronimical Algorithms" by Jean Meeus
  923.   //which was taken in turn from a book "General Astronomy" by Spencer Jones. It has been 
  924.   //published again in the "Journal of the British Astronomical Association, Vol 88" where
  925.   //it is said that it was devised in 1876 and appeared in Butcher's "Ecclesiastical Calendar"
  926.  
  927.   if (InGregorianCalendar(Year, 4, 1))  //in the Gregorain Calendar, Will possibly give results if Calendar
  928.   {                                     //switches from Julian to Gregorian in March or April because then
  929.     int a = (int) (Year % 19);          //the year may be considered Gregorian or Julian
  930.     int b = (int) (Year / 100);
  931.     int c = (int) (Year % 100);
  932.     int d = b / 4;
  933.     int e = b % 4;
  934.     int f = (b+8) / 25;
  935.     int g = (b - f + 1) / 3;
  936.     int h = (19*a + b - d - g + 15) % 30;
  937.     int i = c / 4;
  938.     int k = c % 4;
  939.     int l = (32 + 2*e + 2*i - h -k) % 7;
  940.     int m = (a + 11*h +22*l) / 451;
  941.     int n = (h + l - 7*m + 114) / 31;
  942.     int p = (h + l - 7*m + 114) % 31;
  943.     return CDate(Year, WORD(n), WORD(p+1));
  944.   }
  945.   else              //in the Julian Calendar
  946.   {                          
  947.     int a = (int) (Year % 4);
  948.     int b = (int) (Year % 7);
  949.     int c = (int) (Year % 19);
  950.     int d = (19*c + 15) % 30;
  951.     int e = (2*a + 4*b - d + 34) % 7;
  952.     int f = (d + e + 114) / 31;
  953.     int g = (d + e + 114) % 31;
  954.     return CDate(Year, (WORD) f, (WORD) (g + 1));
  955.   }  
  956. }
  957.  
  958. CDate CDate::CanadaDay(LONG Year)
  959. {
  960.   return CDate(Year, JULY, 1);
  961. }
  962.  
  963. CDate CDate::IndependenceDay(LONG Year) 
  964. {
  965.   return CDate(Year, JULY, 4);
  966. }
  967.  
  968. CDate CDate::BastilleDay(LONG Year) 
  969. {
  970.   return CDate(Year, JULY, 14);
  971. }
  972.  
  973. CDate CDate::ChristmasDay(LONG Year)  
  974. {
  975.   return CDate(Year, DECEMBER, 25);
  976. }
  977.  
  978. BOOL CDate::IsLeap(LONG Year)
  979. {                
  980.   if (InGregorianCalendar(Year, 1, 1))    //Will give incorrect results if Calendar switches
  981.   {                                       //from Julian to Gregorian in the Year 1600 (if any Country did)
  982.     if ((Year % 100) == 0)                
  983.       return ((Year % 400) == 0) ? TRUE : FALSE;
  984.     else
  985.       return ((Year % 4) == 0) ? TRUE : FALSE;
  986.   }
  987.   else                                        
  988.     return ((Year % 4) == 0) ? TRUE : FALSE;
  989.       
  990. }
  991.  
  992. WORD CDate::DaysInYear(LONG Year)
  993. {
  994.   return IsLeap(Year) ? ((WORD) 366) : ((WORD) 365);
  995. }
  996.  
  997. WORD CDate::DaysInMonth(WORD Month, BOOL IsLeap)
  998. {
  999.   SetFebLength(IsLeap);
  1000.   ASSERT(Month >= 1 && Month <= 12);
  1001.   WORD r = MonthLength[Month];
  1002.   ResetFebLength();
  1003.   return r;
  1004. }
  1005.  
  1006. WORD CDate::DaysSinceJan1(WORD Month, WORD Day, BOOL IsLeap)
  1007. {
  1008.   return (WORD) (DaysSinceJan0(Month, Day, IsLeap) - 1);
  1009. }
  1010.  
  1011.  
  1012. WORD CDate::DaysSinceJan0(WORD Month, WORD Day, BOOL IsLeap)
  1013. {            
  1014.   ASSERT(Month >= JANUARY && Month <= DECEMBER);
  1015.   ASSERT(Day <= DaysInMonth(Month, IsLeap) && Day >= 1);
  1016.   int k = IsLeap ? 1 : 2;
  1017.   WORD rVal = (WORD) ((int(275*Month/9)) - (k*int((Month+9)/12)) + Day - 30);
  1018.   return rVal; 
  1019. }
  1020.  
  1021. WORD CDate::DaysSinceJan1() const
  1022. {
  1023.   AssertValid();
  1024.   return (WORD) (*this - CDate(GetYear(), 1, 1));
  1025. }
  1026.  
  1027. WORD CDate::DaysSinceJan0() const
  1028. {
  1029.   AssertValid();
  1030.   return (WORD) (DaysSinceJan1() + 1);
  1031. }
  1032.  
  1033. DateS CDate::GetDate() const
  1034. {
  1035.   //See the comment in CDate::Set(LONG Year, WORD Month, WORD Day)
  1036.   //for references to where the algorithm is taken from
  1037.  
  1038.   AssertValid();
  1039.   BOOL bIsGreg = InGregorianCalendar();
  1040.   BOOL bIsJulian = !bIsGreg;
  1041.   DateS ds;
  1042.   //LONG gdn = m_lDays + 577735L - 2000000000L + 2*bIsJulian;
  1043.   LONG gdn = m_lDays - 1999422265L + 2*bIsJulian;
  1044.   LONG y4 = 1461L;
  1045.   LONG y400 = 146100L - 3*bIsGreg;
  1046.   LONG y100 = 36525L - bIsGreg;
  1047.   BOOL exception=FALSE;
  1048.   ds.lYear = 400*lfloor(gdn, y400);
  1049.   gdn -= y400*lfloor(gdn, y400);       //400 year periods
  1050.   if (gdn > 0L)
  1051.   {
  1052.     ds.lYear += 100*lfloor(gdn, y100);  //100 year periods
  1053.     gdn -= y100*lfloor(gdn, y100);
  1054.     exception = (gdn == 0L && bIsGreg);
  1055.     if (gdn > 0L)
  1056.     {
  1057.       ds.lYear += 4*lfloor(gdn, y4);     //4 year periods
  1058.       gdn -= y4*lfloor(gdn, y4);
  1059.       if (gdn > 0L)
  1060.       {
  1061.         int i=0;
  1062.         while (gdn > 365 && ++i < 4)
  1063.         {
  1064.           ds.lYear++;
  1065.           gdn -= 365L;
  1066.         }
  1067.       }
  1068.     }
  1069.   }
  1070.   if (exception)
  1071.     gdn = 366L; //occurs once every hundred years with Gregorian calendar
  1072.   else
  1073.   {
  1074.     ds.lYear++;
  1075.     gdn++;
  1076.   }
  1077.   SetFebLength(IsLeap(ds.lYear));
  1078.   ds.wMonth = 1;
  1079.   while (ds.wMonth < 13 && gdn > ((LONG) MonthLength[ds.wMonth]))
  1080.     gdn -= MonthLength[ds.wMonth++];
  1081.   if (ds.wMonth == 13)
  1082.   {
  1083.     ds.wMonth = 1;
  1084.     ds.lYear++;
  1085.   }
  1086.   ResetFebLength();
  1087.   ds.wDay = (WORD) gdn;
  1088.   ds.wWday = (WORD) (WeekOfDayModulo(m_lDays, 7) + 1);
  1089.   ds.wYday = DaysSinceJan0(ds.wMonth, ds.wDay, IsLeap(ds.lYear));
  1090.  
  1091.   return ds;
  1092. }
  1093.  
  1094. WORD CDate::GetDay() const
  1095. {
  1096.   AssertValid();
  1097.   return GetDate().wDay;
  1098. }
  1099.  
  1100. WORD CDate::GetMonth() const
  1101. {
  1102.   AssertValid();
  1103.   return GetDate().wMonth;
  1104. }
  1105.  
  1106. LONG CDate::GetYear() const
  1107. {
  1108.   AssertValid();
  1109.   return GetDate().lYear;
  1110. }
  1111.  
  1112. LONG CDate::GetCEBCEYear(BOOL& IsCE) const
  1113. {
  1114.   AssertValid();
  1115.   LONG Year = GetDate().lYear;
  1116.  
  1117.   if (Year > 0)
  1118.   {
  1119.     IsCE = TRUE;
  1120.     return Year;
  1121.   }
  1122.   else
  1123.   {
  1124.     IsCE = FALSE;
  1125.     return labs(GetYear() - 1);
  1126.   }
  1127. }
  1128.  
  1129. WORD CDate::Get2DigitYear() const
  1130. {
  1131.   AssertValid();
  1132.   LONG Year = labs(GetYear());
  1133.   return (WORD) (Year - ((Year/100)*100));
  1134. }
  1135.  
  1136.  
  1137. WORD CDate::GetWeekOfYear() const
  1138. {               
  1139.   AssertValid(); 
  1140.   CDate FirstOfYear(GetYear(), JANUARY, 1, GetBeginingDayOfWeek());
  1141.   LONG diff = *this - FirstOfYear;
  1142.   if (diff < 0)
  1143.     return 0;
  1144.   else
  1145.     return (WORD) (diff/7 + 1);
  1146. }
  1147.  
  1148.  
  1149. WORD CDate::GetWeekOfMonth() const
  1150. {                  
  1151.   AssertValid();
  1152.   CDate FirstOfMonth(GetYear(), GetMonth(), 1, GetBeginingDayOfWeek());
  1153.   LONG diff = *this - FirstOfMonth;
  1154.   if (diff < 0)
  1155.     return 0;
  1156.   else
  1157.     return (WORD) (diff/7 + 1);
  1158. }
  1159.  
  1160. LONG CDate::Since1900Epoch() const
  1161. {
  1162.   AssertValid();
  1163.   return *this - CDate(1900, 1, 1);
  1164. }
  1165.  
  1166. LONG CDate::Since1950Epoch() const
  1167. {
  1168.   AssertValid();
  1169.   return *this - CDate(1950, 1, 1);
  1170. }
  1171.  
  1172. LONG CDate::SinceCTimeEpoch() const
  1173. {
  1174.   AssertValid();  
  1175.   return *this - CDate(1970, 1, 1);
  1176. }
  1177.  
  1178. LONG CDate::Since2000Epoch() const
  1179. {
  1180.   AssertValid();
  1181.   return *this - CDate(2000, 1, 1);
  1182. }
  1183.  
  1184. LONG CDate::JD() const
  1185. {
  1186.   AssertValid();
  1187.   return *this - JDEpoch();
  1188. }
  1189.  
  1190. LONG CDate::GDN() const
  1191. {
  1192.   AssertValid();
  1193.   return m_lDays - 2000000000L;
  1194. }
  1195.  
  1196. LONG CDate::GetValue() const
  1197. {
  1198.   AssertValid();
  1199.   return m_lDays;
  1200. }
  1201.  
  1202. BOOL CDate::IsLeap() const
  1203. {
  1204.   AssertValid();
  1205.   return IsLeap(GetYear());
  1206. }
  1207.  
  1208. WORD CDate::DaysInYear() const
  1209.   AssertValid();
  1210.   return DaysInYear(GetYear());
  1211. }
  1212.  
  1213. WORD CDate::DaysInMonth() const
  1214. {
  1215.   AssertValid();
  1216.   return DaysInMonth(GetMonth(), IsLeap());
  1217. }
  1218.  
  1219. void CDate::AddYear(int Years)
  1220. {
  1221.   AssertValid();
  1222.   LONG Months = Years*12;
  1223.   if (Months >= INT_MIN && Months <= INT_MAX)
  1224.     AddMonth((int) Months);
  1225.   else
  1226.   {
  1227.     ASSERT(FALSE);
  1228.     Set();
  1229.   }
  1230. }
  1231.  
  1232. void CDate::AddMonth(int Months)
  1233. {
  1234.   AssertValid();
  1235.   LONG NewMonth = (LONG) GetMonth();
  1236.   LONG NewYear = GetYear();
  1237.   NewMonth += Months;
  1238.   if ((NewMonth > DECEMBER) || (NewMonth < JANUARY))
  1239.   {
  1240.     NewYear += NewMonth / 12;
  1241.     NewMonth = NewMonth % 12;
  1242.   }
  1243.   if (NewMonth < JANUARY)
  1244.   {
  1245.     --NewYear;
  1246.     NewMonth += 12;
  1247.   }
  1248.  
  1249.   WORD Day = GetDay();
  1250.  
  1251.   WORD MaxDays = DaysInMonth((WORD) NewMonth, IsLeap(NewYear));
  1252.   if (Day > MaxDays)
  1253.     Day = MaxDays;
  1254.   Set(NewYear, (WORD) NewMonth, Day);
  1255. }
  1256.  
  1257. void CDate::AddWeek(int Weeks)
  1258. {
  1259.   AssertValid();
  1260.   *this += 7L*((LONG)Weeks);
  1261. }
  1262.  
  1263. WORD CDate::GetDayOfWeek() const
  1264. {
  1265.   AssertValid();
  1266.   return (WORD) (WeekOfDayModulo(m_lDays, 7) + 1);
  1267. }
  1268.  
  1269. CString CDate::GetStringCEBCEYear() const
  1270. {
  1271.   AssertValid();
  1272.   BOOL bIsCEYear;
  1273.   LONG lCEYear = GetCEBCEYear(bIsCEYear);
  1274.   CString sYear;                    
  1275.   sYear.Format(_T("%ld"), lCEYear);
  1276.   CString rVal;
  1277.   if (bIsCEYear)
  1278.     AfxFormatString1(rVal, IDS_CEYEAR, sYear);
  1279.   else
  1280.     AfxFormatString1(rVal, IDS_BCEYEAR, sYear);
  1281.   return rVal;
  1282. }
  1283.  
  1284. CString CDate::GetFullStringDayOfWeek() const
  1285. {
  1286.   AssertValid();
  1287.   return GetFullStringDayOfWeek(GetDayOfWeek());
  1288. }
  1289.  
  1290. CString CDate::GetAbrStringDayOfWeek() const
  1291. {
  1292.   AssertValid();
  1293.   return GetAbrStringDayOfWeek(GetDayOfWeek());
  1294. }
  1295.  
  1296. CString CDate::GetFullStringMonth() const
  1297. {
  1298.   AssertValid();
  1299.   return GetFullStringMonth(GetMonth());
  1300. }
  1301.  
  1302. CString CDate::GetAbrStringMonth() const
  1303. {
  1304.   AssertValid();
  1305.   return GetAbrStringMonth(GetMonth());
  1306. }
  1307.  
  1308. SYSTEMTIME CDate::GetSYSTEMTIME() const
  1309. {
  1310.   AssertValid();
  1311.   SYSTEMTIME s;
  1312.   s.wYear = 0;
  1313.   s.wMonth = 0;
  1314.   s.wDayOfWeek = 0;
  1315.   s.wDay = 0;
  1316.   s.wHour = 0;
  1317.   s.wMinute = 0;
  1318.   s.wSecond = 0;
  1319.   s.wMilliseconds = 0;
  1320.  
  1321.   DateS ds = GetDate();
  1322.  
  1323.   //handle range errors
  1324.   if ((ds.lYear < 0) || (ds.lYear > USHRT_MAX))
  1325.   {
  1326.     ASSERT(FALSE);
  1327.     s.wYear = 0;
  1328.     return s;
  1329.   }
  1330.   
  1331.   s.wYear = (WORD) ds.lYear;
  1332.   s.wMonth = ds.wMonth;
  1333.   s.wDayOfWeek = (WORD) (ds.wWday - 1);  //SYSTEMTIME uses 0 based indices
  1334.   s.wDay = ds.wDay;
  1335.  
  1336.   return s;
  1337. }                
  1338.                           
  1339. tm CDate::GetTM() const
  1340. {
  1341.   AssertValid();
  1342.   tm rVal;
  1343.   
  1344.   rVal.tm_sec   = 0;
  1345.   rVal.tm_min   = 0;
  1346.   rVal.tm_hour  = 0;
  1347.   rVal.tm_mday  = 0;
  1348.   rVal.tm_mon   = 0;
  1349.   rVal.tm_year  = 0;
  1350.   rVal.tm_wday  = 0;
  1351.   rVal.tm_yday  = 0;
  1352.   rVal.tm_isdst = 0;
  1353.  
  1354.   DateS ds = GetDate(); 
  1355.      
  1356.   long MinYear = 1900L + LONG_MIN;
  1357.   long MaxYear = LONG_MAX;
  1358.  
  1359.   //handle range errors
  1360.   if ((ds.lYear < MinYear) || (ds.lYear > MaxYear))
  1361.   {
  1362.     ASSERT(FALSE);
  1363.     return rVal;
  1364.   }
  1365.   
  1366.   rVal.tm_year = (int) (ds.lYear - 1900L);
  1367.   rVal.tm_mon = ds.wMonth - 1;  //tm struct uses 0 based indices
  1368.   rVal.tm_wday = ds.wWday - 1;  //tm struct uses 0 based indices
  1369.   rVal.tm_mday = ds.wDay; 
  1370.   rVal.tm_wday = ds.wYday - 1; //Returns days since Jan 1
  1371.               
  1372.   return rVal;
  1373. }
  1374.  
  1375. BOOL CDate::IsValid() const
  1376. {
  1377.   return m_bValid;
  1378. }
  1379.  
  1380. LONG CDate::Collate() const
  1381. {
  1382.   AssertValid();
  1383.   DateS s;
  1384.   s = GetDate();
  1385.   return (s.lYear*10000) + (s.wMonth*100) + s.wDay;
  1386. }
  1387.  
  1388. BOOL CDate::InGregorianCalendar() const
  1389. {
  1390.   AssertValid();
  1391.   return m_bInGregCalendar;
  1392. }
  1393.  
  1394. BOOL CDate::InJulianCalendar() const
  1395. {
  1396.   AssertValid();
  1397.   return !m_bInGregCalendar;
  1398. }
  1399.  
  1400. CDate CDate::FirstThisMonth() const
  1401. {
  1402.   AssertValid();
  1403.   DateS s=GetDate();
  1404.   return CDate(s.lYear, s.wMonth, 1);  
  1405. }
  1406.  
  1407. CDate CDate::LastThisMonth() const
  1408. {
  1409.   AssertValid();
  1410.   DateS s = GetDate();
  1411.   return CDate(s.lYear, s.wMonth, DaysInMonth(s.wMonth, IsLeap(s.lYear)));  
  1412. }
  1413.  
  1414. CDate CDate::FirstThisYear() const
  1415. {
  1416.   AssertValid();
  1417.   DateS s = GetDate();
  1418.   CDate d(s.lYear, JANUARY, 1);
  1419.   return d;  
  1420. }
  1421.  
  1422. CDate CDate::LastThisYear() const
  1423. {
  1424.   AssertValid();
  1425.   DateS s = GetDate();
  1426.   CDate d(s.lYear, DECEMBER, 1);
  1427.   return d;  
  1428. }
  1429.  
  1430. CDate& CDate::operator=(const CDate& d)
  1431. {
  1432.   m_lDays = d.m_lDays;
  1433.   m_bInGregCalendar = d.m_bInGregCalendar;
  1434.   m_bValid = d.m_bValid;
  1435.   return *this;
  1436. }
  1437.  
  1438. CDate CDate::operator+(LONG Days) const
  1439. {
  1440.   AssertValid();
  1441.   return CDate(GDN() + Days, EPOCH_GREG);
  1442. }
  1443.  
  1444. LONG CDate::operator-(const CDate& d) const
  1445. {
  1446.   AssertValid();
  1447.   return m_lDays - d.m_lDays;
  1448. }
  1449.  
  1450. CDate CDate::operator-(LONG Days) const
  1451. {
  1452.   AssertValid();
  1453.   return CDate(GDN() - Days, EPOCH_GREG);
  1454. }
  1455.  
  1456. CDate& CDate::operator+=(LONG Days)
  1457. {
  1458.   AssertValid();
  1459.   m_lDays += Days;
  1460.   return *this;
  1461. }
  1462.  
  1463. CDate& CDate::operator-=(LONG Days)
  1464. {
  1465.   AssertValid();
  1466.   m_lDays -= Days;
  1467.   return *this;
  1468. }
  1469.  
  1470. CDate& CDate::operator++()
  1471. {
  1472.   AssertValid();
  1473.   m_lDays++;
  1474.   return *this;
  1475. }
  1476.  
  1477. CDate& CDate::operator--()
  1478. {
  1479.   AssertValid();
  1480.   m_lDays--;
  1481.   return *this;
  1482. }
  1483.  
  1484. BOOL CDate::operator==(const CDate& d) const
  1485. {
  1486.   AssertValid();
  1487.   return m_lDays == d.m_lDays;
  1488. }
  1489.  
  1490. BOOL CDate::operator>(const CDate& d) const
  1491. {
  1492.   AssertValid();
  1493.   return m_lDays > d.m_lDays;
  1494. }
  1495.  
  1496. BOOL CDate::operator>=(const CDate& d) const
  1497. {
  1498.   AssertValid();
  1499.   return m_lDays >= d.m_lDays;
  1500. }
  1501.  
  1502. BOOL CDate::operator<(const CDate& d) const
  1503. {
  1504.   AssertValid();
  1505.   return m_lDays < d.m_lDays;
  1506. }
  1507.  
  1508. BOOL CDate::operator<=(const CDate& d) const
  1509. {
  1510.   AssertValid();
  1511.   return m_lDays <= d.m_lDays;
  1512. }
  1513.  
  1514. BOOL CDate::operator!=(const CDate& d) const
  1515. {
  1516.   AssertValid();
  1517.   return m_lDays != d.m_lDays;
  1518. }
  1519.  
  1520. #ifdef _DEBUG
  1521. void CDate::AssertValid() const
  1522. {
  1523.   CObject::AssertValid();
  1524.   ASSERT(IsValid());
  1525. }
  1526. #endif
  1527.  
  1528. #ifdef _DEBUG
  1529. void CDate::Dump(CDumpContext& dc) const
  1530. {
  1531.   CObject::Dump(dc);
  1532.   if (IsValid())
  1533.     dc << Format() << _T("\n");
  1534.   else
  1535.     dc << _T("Invalid state\n");
  1536. }
  1537. #endif
  1538.  
  1539. /*    //The Following Format parameters are supported
  1540.  
  1541. %a    Abbreviated weekday name
  1542. %A    Full weekday name
  1543. %b    Abbreviated month name
  1544. %B    Full month name
  1545. %d    Day of month as decimal number (01 - 31)
  1546. %j    Day of year as decimal number (001 - 366)
  1547. %m    Month as decimal number (01 - 12)
  1548. %U    Week of year as decimal number
  1549. %w    Weekday as decimal number (1 - 7; Sunday is 1)
  1550. %x    Short date representation, appropriate to current locale
  1551. %y    Year without century, as decimal number (00 - 99)
  1552. %Y    Year with century, as decimal number
  1553. %c    Year displayed using C.E.(Current Epoch) / B.C.E (Before Current Epoch) convention e.g. -1023 = 1022 BCE
  1554. %#x   Long date representation, appropriate to current locale
  1555. %#d, %#j, %#m, %#U, %#y Remove leading zeros (if any)
  1556. */
  1557. CString CDate::Format(const CString& sFormat) const
  1558.   CString rVal;
  1559.   if (IsValid())
  1560.   {
  1561.     CString sBuffer;
  1562.     int sFmtLength = sFormat.GetLength();
  1563.  
  1564.     for (int i=0; i<sFmtLength; i++)
  1565.     {
  1566.       TCHAR c = sFormat.GetAt(i);
  1567.       if (c == _T('%'))
  1568.       {
  1569.         ++i;
  1570.         if (i < sFmtLength)
  1571.         {
  1572.           c = sFormat.GetAt(i);
  1573.           switch (c)
  1574.           {
  1575.             case _T('a'):
  1576.             {
  1577.               rVal += GetAbrStringDayOfWeek();
  1578.               break;
  1579.             }
  1580.             case _T('A'):
  1581.             {
  1582.               rVal += GetFullStringDayOfWeek();
  1583.               break;
  1584.             }
  1585.             case _T('b'):
  1586.             {
  1587.               rVal += GetAbrStringMonth();
  1588.               break;
  1589.             }
  1590.             case _T('c'):
  1591.             {
  1592.               rVal += GetStringCEBCEYear();
  1593.               break;
  1594.             }
  1595.             case _T('B'):
  1596.             {
  1597.               rVal += GetFullStringMonth();
  1598.               break;
  1599.             }
  1600.             case _T('d'):
  1601.             {
  1602.               sBuffer.Format(_T("%.02d"), GetDay());
  1603.               rVal += sBuffer;
  1604.               break;
  1605.             }
  1606.             case _T('j'):
  1607.             {
  1608.               sBuffer.Format(_T("%.03d"), DaysSinceJan0());
  1609.               rVal += sBuffer;
  1610.               break;
  1611.             }
  1612.             case _T('m'):
  1613.             {
  1614.               sBuffer.Format(_T("%.02d"), GetMonth());
  1615.               rVal += sBuffer;
  1616.               break;
  1617.             }
  1618.             case _T('U'):
  1619.             {
  1620.               sBuffer.Format(_T("%.02d"), GetWeekOfYear());
  1621.               rVal += sBuffer;
  1622.               break;
  1623.             }
  1624.             case _T('w'):
  1625.             {
  1626.               sBuffer.Format(_T("%d"), GetDayOfWeek());
  1627.               rVal += sBuffer;
  1628.               break;
  1629.             }                                   
  1630.             case _T('x'):
  1631.             {
  1632.               sBuffer.Empty();
  1633.               SYSTEMTIME st = GetSYSTEMTIME();
  1634.               int Res = ::GetDateFormat(LOCALE_USER_DEFAULT,
  1635.                                       DATE_SHORTDATE,
  1636.                                       &st,
  1637.                                       NULL,
  1638.                                       sBuffer.GetBufferSetLength(100),
  1639.                                       100); 
  1640.               if (Res == 0)
  1641.                 TRACE1("GetDateFormat() Failed in CDate::Format(), GetLastError() returned %ul\n", ::GetLastError());
  1642.               sBuffer.ReleaseBuffer();
  1643.               rVal += sBuffer;
  1644.               break;
  1645.             }                 
  1646.             case _T('y'):
  1647.             {
  1648.               LONG Year = GetYear();
  1649.               sBuffer.Format(_T("%.02d"), Get2DigitYear());
  1650.               rVal += sBuffer;
  1651.               break;
  1652.             }
  1653.             case _T('Y'):
  1654.             {
  1655.               sBuffer.Format(_T("%ld"), GetYear());
  1656.               rVal += sBuffer;
  1657.               break;
  1658.             }
  1659.             case _T('#'):
  1660.             {
  1661.               if (i < sFmtLength)
  1662.               {
  1663.                 ++i;
  1664.                 c = sFormat.GetAt(i);
  1665.                 switch (c)
  1666.                 {
  1667.                   case _T('d'):
  1668.                   {
  1669.                     sBuffer.Format(_T("%d"), GetDay());
  1670.                     rVal += sBuffer;
  1671.                     break;
  1672.                   }
  1673.                   case _T('j'):
  1674.                   {
  1675.                     sBuffer.Format(_T("%d"), DaysSinceJan0());
  1676.                     rVal += sBuffer;
  1677.                     break;
  1678.                   }
  1679.                   case _T('m'):
  1680.                   {
  1681.                     sBuffer.Format(_T("%d"), GetMonth());
  1682.                     rVal += sBuffer;
  1683.                     break;
  1684.                   }
  1685.                   case _T('U'):
  1686.                   {
  1687.                     sBuffer.Format(_T("%d"), GetWeekOfYear());
  1688.                     rVal += sBuffer;
  1689.                     break;
  1690.                   }                                    
  1691.                   case _T('x'):
  1692.                   {
  1693.                     sBuffer.Empty();
  1694.                     SYSTEMTIME st = GetSYSTEMTIME();
  1695.                     int Res = ::GetDateFormat(LOCALE_USER_DEFAULT,
  1696.                                             DATE_LONGDATE,
  1697.                                             &st,
  1698.                                             NULL,
  1699.                                             sBuffer.GetBufferSetLength(100),
  1700.                                             100); 
  1701.                     if (Res == 0)
  1702.                       TRACE1("GetDateFormat() Failed in CDate::Format(), GetLastError() returned %ul\n", ::GetLastError());
  1703.  
  1704.                     sBuffer.ReleaseBuffer();
  1705.                     rVal += sBuffer;
  1706.                     break;
  1707.                   }               
  1708.                   case _T('y'):
  1709.                   {
  1710.                     LONG Year = GetYear();
  1711.                     sBuffer.Format(_T("%d"), Get2DigitYear());
  1712.                     rVal += sBuffer;
  1713.                     break;
  1714.                   }
  1715.                   default:
  1716.                   {
  1717.                     rVal += c;
  1718.                     break;
  1719.                   }
  1720.                 }
  1721.               }
  1722.               break;
  1723.             }
  1724.             default:
  1725.             {
  1726.               rVal += c;
  1727.               break;
  1728.             }
  1729.           }
  1730.         }
  1731.       }
  1732.       else
  1733.       {
  1734.         rVal += c;
  1735.       }
  1736.     }
  1737.   }
  1738.  
  1739.   return rVal;
  1740. }
  1741.  
  1742. //Format according to the short date format as specified by the control panel
  1743. CString CDate::Format() const
  1744. {
  1745.   return Format(sm_sDefaultFormat);
  1746. }
  1747.  
  1748. void CDate::GetDefaultFormat()
  1749. {
  1750.   CString sBuf;
  1751.  
  1752.   // Is there to be a leading 0 on the day?
  1753.   BOOL bDayLZ = FALSE;
  1754.   LPTSTR pszBuf = sBuf.GetBuffer(10);
  1755.   int nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDAYLZERO, pszBuf, 10);
  1756.   ASSERT(nChars);
  1757.   sBuf.ReleaseBuffer();
  1758.   if (sBuf == _T("0"))  //No leading zeros for days
  1759.     bDayLZ = FALSE;
  1760.   else if (sBuf == _T("1"))  //Leading zeros for days
  1761.     bDayLZ = TRUE;
  1762.   else
  1763.     ASSERT(FALSE);
  1764.  
  1765.   // Is there to be a leading 0 on the month?
  1766.   BOOL bMoLZ = TRUE;
  1767.   pszBuf = sBuf.GetBuffer(10);
  1768.   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMONLZERO, pszBuf, 10);
  1769.   ASSERT(nChars);
  1770.   sBuf.ReleaseBuffer();
  1771.   if (sBuf == _T("0"))  //No leading zeros for months
  1772.     bMoLZ = FALSE;
  1773.   else if (sBuf == _T("1"))  //Leading zeros for months
  1774.     bMoLZ = TRUE;
  1775.   else
  1776.     ASSERT(FALSE);
  1777.  
  1778.  
  1779.   // Find if only 2 digits are to be displayed for the year
  1780.   BOOL b2DigitYear = FALSE;
  1781.  
  1782.   //Because DTime can allow years to be much larger than 4 digits in size,
  1783.   //DTime always explicitly shows all the year digits, instead of looking
  1784.   //at the LOCALE_ICENTURY LCTYPE, but commented out below is the code
  1785.   //that would be required for those interested
  1786.  
  1787.   /*
  1788.   pszBuf = sBuf.GetBuffer(10);
  1789.   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ICENTURY, pszBuf, 10);
  1790.   ASSERT(nChars);
  1791.   sBuf.ReleaseBuffer();
  1792.   if (sBuf == _T("0"))  //Abbreviated 2-digit century
  1793.     b2DigitYear = TRUE;
  1794.   else if (sBuf == _T("1"))  //Full century
  1795.     b2DigitYear = FALSE;
  1796.   else
  1797.     ASSERT(FALSE);
  1798.   */
  1799.   
  1800.  
  1801.   // Get the date separator character
  1802.   CString sSep(_T("/"));
  1803.   pszBuf = sSep.GetBuffer(10);
  1804.   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, pszBuf, 10);
  1805.   ASSERT(nChars);
  1806.   sSep.ReleaseBuffer();
  1807.  
  1808.  
  1809.   //Retrieve the short date formatting string
  1810.   pszBuf = sBuf.GetBuffer(10);
  1811.   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDATE, pszBuf, 10);
  1812.   ASSERT(nChars);
  1813.   sBuf.ReleaseBuffer();
  1814.  
  1815.  
  1816.   //Format according to the short date formatting string     //THESE CODES NEED TO BE CHECKED
  1817.   if (sBuf == _T("0"))  //MDY format
  1818.   {
  1819.     if (b2DigitYear)
  1820.       sm_sDefaultFormat.Format(_T("%s%s%s%s%%y"), bMoLZ ? _T("%m") : _T("%#m"), sSep, bDayLZ ? _T("%d") : _T("%#d"), sSep);
  1821.     else
  1822.       sm_sDefaultFormat.Format(_T("%s%s%s%s%%Y"), bMoLZ ? _T("%m") : _T("%#m"), sSep, bDayLZ ? _T("%d") : _T("%#d"), sSep);
  1823.   }
  1824.   else if (sBuf == _T("1"))  //DMY format
  1825.   {
  1826.     if (b2DigitYear)
  1827.       sm_sDefaultFormat.Format(_T("%s%s%s%s%%y"), bDayLZ ? _T("%d") : _T("%#d"), sSep, bMoLZ ? _T("%m") : _T("%#m"), sSep);
  1828.     else
  1829.       sm_sDefaultFormat.Format(_T("%s%s%s%s%%Y"), bDayLZ ? _T("%d") : _T("%#d"), sSep, bMoLZ ? _T("%m") : _T("%#m"), sSep);
  1830.   }
  1831.   else 
  1832.   {
  1833.     if (sBuf != _T("2"))  //No Recognized format available
  1834.       ASSERT(FALSE);
  1835.  
  1836.     //YMD Format
  1837.     if (b2DigitYear)
  1838.       sm_sDefaultFormat.Format(_T("%%y%s%s%s%s"), sSep, bMoLZ ? _T("%m") : _T("%#m"), sSep, bDayLZ ? _T("%d") : _T("%#d"));
  1839.     else
  1840.       sm_sDefaultFormat.Format(_T("%%Y%s%s%s%s"), sSep, bMoLZ ? _T("%m") : _T("%#m"), sSep, bDayLZ ? _T("%d") : _T("%#d"));
  1841.   }
  1842. }
  1843.  
  1844.  
  1845. void CDate::Serialize(CArchive& ar)
  1846. {
  1847.   CObject::Serialize(ar);
  1848.  
  1849.   if (ar.IsStoring())
  1850.   {
  1851.     ar << m_lDays;
  1852.     ar << (WORD) m_bInGregCalendar;
  1853.     ar << m_bValid;
  1854.   }
  1855.   else
  1856.   {
  1857.     ar >> m_lDays;
  1858.     ar >> (WORD&) m_bInGregCalendar;
  1859.     ar >> m_bValid;
  1860.   }
  1861. }
  1862.  
  1863. ostream& operator<<(ostream& os, const CDate& date)
  1864. {
  1865.   return os << date.Format();
  1866. }
  1867.  
  1868. CArchive& operator<<(CArchive& ar, CDate& date)
  1869. {
  1870.   ASSERT(ar.IsStoring());
  1871.   date.Serialize(ar);
  1872.   return ar;
  1873. }
  1874.  
  1875. CArchive& operator>>(CArchive& ar, CDate& date)
  1876. {
  1877.   ASSERT(!ar.IsStoring());
  1878.   date.Serialize(ar);
  1879.   return ar;
  1880. }
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886.  
  1887.  
  1888. //CLTimeSpan Implementation
  1889.  
  1890.  
  1891. CLTimeSpan::CLTimeSpan()
  1892. {
  1893.   Set();
  1894. }
  1895.  
  1896. CLTimeSpan::CLTimeSpan(LONG Day, WORD Hour, WORD Minute, 
  1897.                        WORD Second)
  1898. {
  1899.   Set(Day, Hour, Minute, Second);
  1900. }
  1901.  
  1902. CLTimeSpan::CLTimeSpan(const CLTimeSpan& lts)
  1903. {
  1904.   m_nSeconds = lts.m_nSeconds;
  1905.   m_bValid   = lts.m_bValid;
  1906. }
  1907.  
  1908. CLTimeSpan::CLTimeSpan(const CTimeSpan& ts)
  1909. {
  1910.   Set(ts);
  1911. }
  1912.  
  1913. CLTimeSpan::CLTimeSpan(const CLTimeOfDay& tod)
  1914. {
  1915.   Set(tod);
  1916. }
  1917.       
  1918. CLTimeSpan::CLTimeSpan(const COleDateTimeSpan& oleTimeSpan)
  1919. {
  1920.   Set(oleTimeSpan);
  1921. }                     
  1922.  
  1923. CLTimeSpan::CLTimeSpan(const __int64& Seconds)
  1924. {
  1925.   Set(Seconds);
  1926. }
  1927.  
  1928. CLTimeSpan& CLTimeSpan::Set()
  1929. {                          
  1930.   m_nSeconds = 0;
  1931.   m_bValid = FALSE;
  1932.   return *this;
  1933. }
  1934.  
  1935. CLTimeSpan& CLTimeSpan::Set(LONG Day, WORD Hour, WORD Minute, 
  1936.                             WORD Second)
  1937.   if (Day >= 0)
  1938.     m_nSeconds = __int64(Day)*86400L + __int64(Hour)*3600L + __int64(Minute)*60L + Second;
  1939.   else
  1940.     m_nSeconds = __int64(Day)*86400L - __int64(Hour)*3600L - __int64(Minute)*60L - Second;
  1941.   m_bValid = TRUE;
  1942.   return *this;
  1943. }                            
  1944.  
  1945. CLTimeSpan& CLTimeSpan::Set(const CTimeSpan& ts)
  1946. {
  1947.   m_nSeconds = ts.GetTotalSeconds();
  1948.   m_bValid   = TRUE;
  1949.   return *this;
  1950. }
  1951.  
  1952. CLTimeSpan& CLTimeSpan::Set(const CLTimeOfDay& tod)
  1953. {
  1954.   Set(0, tod.GetHour(), tod.GetMinute(), tod.GetSecond());
  1955.   return *this;
  1956. }
  1957.       
  1958. CLTimeSpan& CLTimeSpan::Set(const COleDateTimeSpan& oleTimeSpan)
  1959. {
  1960.   COleDateTimeSpan::DateTimeSpanStatus dtss(oleTimeSpan.GetStatus());
  1961.   CLTimeSpan rVal;
  1962.   if (dtss == COleDateTimeSpan::DateTimeSpanStatus::valid)
  1963.     Set(oleTimeSpan.GetTotalSeconds());
  1964.   else
  1965.     Set();
  1966.   return *this;
  1967. }                     
  1968.  
  1969. CLTimeSpan& CLTimeSpan::Set(const __int64& Seconds)
  1970.   m_nSeconds = Seconds;
  1971.   m_bValid = TRUE;
  1972.   return *this;
  1973. }
  1974.  
  1975. CLTimeSpan CLTimeSpan::OneCivilYear()
  1976. {
  1977.   return CLTimeSpan(365, 6, 0, 0);
  1978. }
  1979.  
  1980. CLTimeSpan CLTimeSpan::OneDay()
  1981. {
  1982.   return CLTimeSpan(1, 0, 0, 0);
  1983. }
  1984.  
  1985. CLTimeSpan CLTimeSpan::OneHour()
  1986. {
  1987.   return CLTimeSpan(0, 1, 0, 0);
  1988. }
  1989.  
  1990. CLTimeSpan CLTimeSpan::OneMinute()
  1991. {
  1992.   return CLTimeSpan(0, 0, 1, 0);
  1993. }
  1994.  
  1995. CLTimeSpan CLTimeSpan::OneSecond()
  1996. {
  1997.   return CLTimeSpan(0, 0, 0, 1);
  1998. }
  1999.  
  2000. #ifdef _DEBUG
  2001. BOOL CLTimeSpan::SetDoConstructorAsserts(BOOL bDoAsserts)
  2002. {
  2003.   BOOL bOldDoAsserts = sm_bDoAsserts;
  2004.   sm_bDoAsserts = bDoAsserts;
  2005.   return bOldDoAsserts;
  2006. }
  2007. #endif                     
  2008.  
  2009. LONG CLTimeSpan::GetTotalDays() const
  2010. {
  2011.   AssertValid();
  2012.   return (LONG) (m_nSeconds/86400);
  2013. }
  2014.  
  2015. WORD CLTimeSpan::GetHours() const
  2016. {
  2017.   AssertValid();
  2018.  
  2019.   if (IsPositiveSpan())
  2020.     return (WORD) ((m_nSeconds - 86400*__int64(GetTotalDays()))/3600L);
  2021.   else
  2022.   {
  2023.     CLTimeSpan n(*this);
  2024.     n.Negate();
  2025.     return n.GetHours();
  2026.   }  
  2027. }
  2028.  
  2029. WORD CLTimeSpan::GetMinutes() const
  2030. {
  2031.   AssertValid();
  2032.  
  2033.   if (IsPositiveSpan())
  2034.     return (WORD) ((m_nSeconds - 86400*__int64(GetTotalDays()) - 3600*GetHours())/60);
  2035.   else
  2036.   {
  2037.     CLTimeSpan n(*this);
  2038.     n.Negate();
  2039.     return n.GetMinutes();
  2040.   }  
  2041. }
  2042.  
  2043. WORD CLTimeSpan::GetSeconds() const
  2044. {
  2045.   AssertValid();
  2046.  
  2047.   if (IsPositiveSpan())
  2048.     return (WORD) (m_nSeconds - 86400*__int64(GetTotalDays()) - 3600*GetHours() - 60*GetMinutes());
  2049.   else
  2050.   {
  2051.     CLTimeSpan n(*this);
  2052.     n.Negate();
  2053.     return n.GetSeconds();
  2054.   }  
  2055. }                             
  2056.  
  2057. BOOL CLTimeSpan::IsValid() const
  2058. {
  2059.   return m_bValid;
  2060. }
  2061.  
  2062. CLTimeSpan& CLTimeSpan::Negate()
  2063. {
  2064.   AssertValid();
  2065.   m_nSeconds = (-m_nSeconds);
  2066.   return *this;
  2067. }
  2068.  
  2069. BOOL CLTimeSpan::IsPositiveSpan() const
  2070. {
  2071.   AssertValid();
  2072.   return (m_nSeconds >= 0);
  2073. }
  2074.  
  2075. double CLTimeSpan::SecondsAsDouble() const
  2076. {
  2077.   AssertValid();
  2078.   return (double) m_nSeconds;
  2079. }
  2080.  
  2081. BOOL CLTimeSpan::operator==(const CLTimeSpan& TimeSpan) const
  2082. {
  2083.   AssertValid();
  2084.   return (m_nSeconds == TimeSpan.m_nSeconds);
  2085. }
  2086.  
  2087. BOOL CLTimeSpan::operator>(const CLTimeSpan& TimeSpan) const
  2088. {
  2089.   AssertValid();
  2090.   return (m_nSeconds > TimeSpan.m_nSeconds);
  2091. }
  2092.  
  2093. BOOL CLTimeSpan::operator>=(const CLTimeSpan& TimeSpan) const
  2094. {
  2095.   AssertValid();
  2096.   return (m_nSeconds >= TimeSpan.m_nSeconds);
  2097. }
  2098.  
  2099. BOOL CLTimeSpan::operator<(const CLTimeSpan& TimeSpan) const
  2100. {
  2101.   AssertValid();
  2102.   return (m_nSeconds < TimeSpan.m_nSeconds);
  2103. }
  2104.  
  2105. BOOL CLTimeSpan::operator<=(const CLTimeSpan& TimeSpan) const
  2106. {
  2107.   AssertValid();
  2108.   return (m_nSeconds <= TimeSpan.m_nSeconds);
  2109. }
  2110.  
  2111. BOOL CLTimeSpan::operator!=(const CLTimeSpan& TimeSpan) const
  2112. {
  2113.   AssertValid();
  2114.   return (m_nSeconds != TimeSpan.m_nSeconds);
  2115. }
  2116.                                  
  2117. CLTimeSpan& CLTimeSpan::operator=(const CLTimeSpan& TimeSpan)
  2118.   m_nSeconds = TimeSpan.m_nSeconds;
  2119.   m_bValid = TimeSpan.m_bValid;
  2120.   return *this;
  2121. }
  2122.  
  2123. CLTimeSpan CLTimeSpan::operator+(const CLTimeSpan& TimeSpan) const
  2124. {
  2125.   AssertValid();
  2126.   TimeSpan.AssertValid();
  2127.   __int64 rVal = m_nSeconds + TimeSpan.m_nSeconds;
  2128.   return CLTimeSpan(rVal);
  2129. }
  2130.  
  2131. CLTimeSpan CLTimeSpan::operator-(const CLTimeSpan& TimeSpan) const
  2132. {
  2133.   AssertValid();
  2134.   TimeSpan.AssertValid();
  2135.   __int64 rVal = m_nSeconds - TimeSpan.m_nSeconds;
  2136.   return rVal;
  2137. }
  2138.  
  2139. CLTimeSpan& CLTimeSpan::operator+=(CLTimeSpan& TimeSpan)
  2140. {
  2141.   *this = *this + TimeSpan;
  2142.   return *this;
  2143. }
  2144.  
  2145. CLTimeSpan& CLTimeSpan::operator-=(CLTimeSpan& TimeSpan)
  2146. {
  2147.   *this = *this - TimeSpan;
  2148.   return *this;
  2149. }
  2150.  
  2151. CLTimeSpan operator-(const CLTimeSpan& TimeSpan)
  2152. {
  2153.   CLTimeSpan rVal(TimeSpan);
  2154.   return rVal.Negate();
  2155. }
  2156.  
  2157. CLTimeSpan CLTimeSpan::operator*(WORD Multiplier) const
  2158. {
  2159.   return ::operator*(Multiplier, *this);
  2160. }
  2161.  
  2162. CLTimeSpan operator*(WORD Multiplier, const CLTimeSpan& TimeSpan)
  2163. {
  2164.   TimeSpan.AssertValid();
  2165.   __int64 rVal = TimeSpan.m_nSeconds * Multiplier;
  2166.   return CLTimeSpan(rVal);
  2167. }
  2168.  
  2169. CLTimeSpan CLTimeSpan::operator/(WORD divisor) const
  2170. {
  2171.   AssertValid();
  2172.   __int64 rVal = m_nSeconds / divisor;
  2173.   return CLTimeSpan(rVal);
  2174. }
  2175.  
  2176. CLTimeSpan& CLTimeSpan::operator*=(WORD Multiplier)
  2177. {
  2178.   *this = operator*(Multiplier);
  2179.   return *this;
  2180. }
  2181.  
  2182. CLTimeSpan& CLTimeSpan::operator/=(WORD Divisor)
  2183. {
  2184.   *this = operator/(Divisor);
  2185.   return *this;
  2186. }
  2187.  
  2188. #ifdef _DEBUG
  2189. void CLTimeSpan::AssertValid() const
  2190. {
  2191.   CObject::AssertValid();
  2192.   ASSERT(IsValid());
  2193. }
  2194. #endif
  2195.  
  2196. #ifdef _DEBUG
  2197. void CLTimeSpan::Dump(CDumpContext& dc) const
  2198. {
  2199.   CObject::Dump(dc);
  2200.   if (IsValid())
  2201.     dc << Format() << _T("\n");
  2202.   else
  2203.     dc << _T("Invalid state\n");
  2204. }
  2205. #endif
  2206.  
  2207. /*    //The Following Format parameters are supported        
  2208. %D    Total days in this CLTimeSpan
  2209. %H    Hours in this CLTimeSpan (00 - 23)
  2210. %M    Minutes in the current hour in this CLTimeSpan (00 - 59)
  2211. %S    Seconds in the current minute in this CLTimeSpan (00 - 59)
  2212. %%    Percent sign
  2213. %#H, %#M, %#S  Remove leading zeros (if any).
  2214. */
  2215. CString CLTimeSpan::Format(const CString& sFormat) const
  2216.   CString rVal;
  2217.   if (IsValid())
  2218.   {
  2219.     CString sBuffer;
  2220.     int sFmtLength = sFormat.GetLength();
  2221.  
  2222.     for (int i=0; i<sFmtLength; i++)
  2223.     {
  2224.       TCHAR c = sFormat.GetAt(i);
  2225.       if (c == _T('%'))
  2226.       {
  2227.         ++i;
  2228.         if (i < sFmtLength)
  2229.         {
  2230.           c = sFormat.GetAt(i);
  2231.           switch (c)
  2232.           {
  2233.             case _T('D'):
  2234.             {
  2235.               LONG Days = GetTotalDays();
  2236.               sBuffer.Format(_T("%ld"), Days);
  2237.               if (IsPositiveSpan())
  2238.                 rVal += _T("+");
  2239.               else if (Days == 0) //handle neagtive 0
  2240.                 rVal += _T("-");
  2241.               rVal += sBuffer;
  2242.               break;
  2243.             }
  2244.             case _T('H'):
  2245.             {
  2246.               sBuffer.Format(_T("%.02d"), GetHours());
  2247.               rVal += sBuffer;
  2248.               break;
  2249.             }
  2250.             case _T('M'):
  2251.             {
  2252.               sBuffer.Format(_T("%.02d"), GetMinutes());
  2253.               rVal += sBuffer;
  2254.               break;
  2255.             }
  2256.             case _T('S'):
  2257.             {
  2258.               sBuffer.Format(_T("%.02d"), GetSeconds());
  2259.               rVal += sBuffer;
  2260.               break;
  2261.             }
  2262.             case _T('#'):
  2263.             {
  2264.               if (i < sFmtLength)
  2265.               {
  2266.                 ++i;
  2267.                 c = sFormat.GetAt(i);
  2268.                 switch (c)
  2269.                 {
  2270.                   case _T('H'):
  2271.                   {
  2272.                     sBuffer.Format(_T("%d"), GetHours());
  2273.                     rVal += sBuffer;
  2274.                     break;
  2275.                   }
  2276.                   case _T('M'):
  2277.                   {
  2278.                     sBuffer.Format(_T("%d"), GetMinutes());
  2279.                     rVal += sBuffer;
  2280.                     break;
  2281.                   }
  2282.                   case _T('S'):
  2283.                   {
  2284.                     sBuffer.Format(_T("%d"), GetSeconds());
  2285.                     rVal += sBuffer;
  2286.                     break;
  2287.                   }
  2288.                   default:
  2289.                   {
  2290.                     rVal += c;
  2291.                     break;
  2292.                   }
  2293.                 }
  2294.               break;
  2295.               }
  2296.             }
  2297.             default:
  2298.             {
  2299.               rVal += c;
  2300.               break;
  2301.             }
  2302.           }
  2303.         }
  2304.       }
  2305.       else
  2306.       {
  2307.         rVal += c;
  2308.       }
  2309.     }
  2310.   }
  2311.   
  2312.   return rVal;
  2313. }
  2314.  
  2315. //Format according to the time format as specified by the control panel
  2316. CString CLTimeSpan::Format(DWORD dwFlags) const
  2317. {
  2318.   if (dwFlags & DTF_NOSECOND)
  2319.     return Format(sm_sDefaultFormatNOS);
  2320.   else
  2321.     return Format(sm_sDefaultFormat);
  2322. }
  2323.  
  2324. void CLTimeSpan::GetDefaultFormat()
  2325. {
  2326.   CString sBuf;
  2327.  
  2328.   // Is there to be a leading 0 on the Hour?
  2329.   BOOL bHourLZ = FALSE;
  2330.   LPTSTR pszBuf = sBuf.GetBuffer(10);
  2331.   int nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, pszBuf, 10);
  2332.   ASSERT(nChars);
  2333.   sBuf.ReleaseBuffer();
  2334.   if (sBuf == _T("0"))  //No leading zeros for hours
  2335.     bHourLZ = FALSE;
  2336.   else if (sBuf == _T("1"))  //Leading zeros for hours
  2337.     bHourLZ = TRUE;
  2338.   else
  2339.     ASSERT(FALSE);
  2340.  
  2341.   // Get the time separator character
  2342.   CString sSep(_T(":"));
  2343.   pszBuf = sSep.GetBuffer(10);
  2344.   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, pszBuf, 10);
  2345.   ASSERT(nChars);
  2346.   sSep.ReleaseBuffer();
  2347.  
  2348.   //Modify behaviour depending on the various flags
  2349.   if (bHourLZ)
  2350.   {
  2351.     sm_sDefaultFormatNOS.Format(_T("%%D %%H%s%%M"), sSep);
  2352.     sm_sDefaultFormat.Format(_T("%%D %%H%s%%M%s%%S"), sSep, sSep);
  2353.   }
  2354.   else
  2355.   {
  2356.     sm_sDefaultFormatNOS.Format(_T("%%D %%#H%s%%M"), sSep);
  2357.     sm_sDefaultFormat.Format(_T("%%D %%#H%s%%M%s%%S"), sSep, sSep);
  2358.   }
  2359. }
  2360.  
  2361. void CLTimeSpan::Serialize(CArchive& ar)
  2362. {
  2363.   CObject::Serialize(ar);
  2364.  
  2365.   if (ar.IsStoring())
  2366.   {
  2367.     ar << m_nSeconds;
  2368.     ar << m_bValid;
  2369.   }
  2370.   else
  2371.   {
  2372.     ar >> m_nSeconds;
  2373.     ar >> m_bValid;
  2374.   }
  2375. }
  2376.  
  2377. ostream& operator<<(ostream &os, const CLTimeSpan& TimeSpan)
  2378. {
  2379.   return os << TimeSpan.Format();
  2380. }                  
  2381.  
  2382. CArchive& operator<<(CArchive& ar, CLTimeSpan& TimeSpan)
  2383. {
  2384.   ASSERT(ar.IsStoring());
  2385.   TimeSpan.Serialize(ar);
  2386.   return ar;
  2387. }
  2388.                
  2389. CArchive& operator>>(CArchive& ar, CLTimeSpan& TimeSpan)
  2390. {
  2391.   ASSERT(!ar.IsStoring());
  2392.   TimeSpan.Serialize(ar);
  2393.   return ar;
  2394. }
  2395.  
  2396.  
  2397.  
  2398.  
  2399.  
  2400.  
  2401. //CLTimeOfDay Implementation
  2402.  
  2403. CLTimeOfDay::CLTimeOfDay()
  2404. {
  2405.   Set();
  2406. }
  2407.  
  2408. CLTimeOfDay::CLTimeOfDay(WORD Hour, WORD Minute, WORD Second)
  2409. {
  2410.   Set(Hour, Minute, Second);
  2411. }    
  2412.  
  2413. CLTimeOfDay::CLTimeOfDay(const SYSTEMTIME& st)
  2414. {        
  2415.   Set(st);
  2416. }
  2417.            
  2418. CLTimeOfDay::CLTimeOfDay(const CLTimeOfDay& ltod)
  2419. {
  2420.   m_dwTotalSeconds = ltod.m_dwTotalSeconds;
  2421.   m_bValid = ltod.m_bValid;
  2422. }                                
  2423.  
  2424. CLTimeOfDay::CLTimeOfDay(DWORD TotalSeconds)
  2425. {
  2426.   Set(TotalSeconds);
  2427. }                                
  2428.  
  2429.  
  2430. CLTimeOfDay& CLTimeOfDay::Set()
  2431. {
  2432.   m_dwTotalSeconds = 0;
  2433.   m_bValid = FALSE;
  2434.   return *this;
  2435. }
  2436.  
  2437. CLTimeOfDay& CLTimeOfDay::Set(WORD Hour, WORD Minute, WORD Second)
  2438. {
  2439.   m_dwTotalSeconds = Hour*3600 + Minute*60 + Second;
  2440.   if (m_dwTotalSeconds >= 86400L)
  2441.   {
  2442.     if (sm_bDoAsserts)
  2443.       ASSERT(FALSE);
  2444.     Set();
  2445.     return *this;
  2446.   }
  2447.  
  2448.   m_bValid = TRUE;
  2449.   return *this;  
  2450. }                
  2451.  
  2452. CLTimeOfDay& CLTimeOfDay::Set(const SYSTEMTIME& st)
  2453. {        
  2454.   return Set(st.wHour, st.wMinute, st.wSecond);
  2455. }
  2456.                                  
  2457. CLTimeOfDay& CLTimeOfDay::Set(DWORD TotalSeconds)
  2458. {
  2459.   m_dwTotalSeconds = TotalSeconds;
  2460.   if (m_dwTotalSeconds >= 86400)
  2461.   {
  2462.     if (sm_bDoAsserts)
  2463.       ASSERT(FALSE);
  2464.     Set();
  2465.     return *this;
  2466.   }
  2467.  
  2468.   m_bValid = TRUE;
  2469.   return *this;  
  2470. }
  2471.                                  
  2472. CLTimeOfDay CLTimeOfDay::CurrentTimeOfDay(TimeFrame tf)
  2473.   SYSTEMTIME st;                                
  2474.   switch (tf)
  2475.   {    
  2476.     case UCT:
  2477.       ::GetSystemTime(&st); 
  2478.       break;
  2479.     case LOCAL:
  2480.       ::GetLocalTime(&st); 
  2481.       break;   
  2482.     case ET:
  2483.       ASSERT(FALSE);
  2484.       break;
  2485.     default: ASSERT(FALSE);
  2486.   }    
  2487.       
  2488.   return CLTimeOfDay(st);
  2489. }
  2490.                                  
  2491. CLTimeOfDay CLTimeOfDay::Midnight()
  2492. {
  2493.   return CLTimeOfDay(0, 0, 0);
  2494. }
  2495.  
  2496. CLTimeOfDay CLTimeOfDay::Midday()
  2497. {
  2498.   return CLTimeOfDay(12, 0, 0);
  2499. }
  2500.  
  2501. #ifdef _DEBUG
  2502. BOOL CLTimeOfDay::SetDoConstructorAsserts(BOOL bDoAsserts)
  2503. {
  2504.   BOOL bOldDoAsserts = sm_bDoAsserts;
  2505.   sm_bDoAsserts = bDoAsserts;
  2506.   return bOldDoAsserts;
  2507. }
  2508. #endif                 
  2509.  
  2510. WORD CLTimeOfDay::GetHour() const
  2511. {
  2512.   AssertValid();
  2513.   return (WORD) (m_dwTotalSeconds/3600L);
  2514. }
  2515.  
  2516. WORD CLTimeOfDay::GetMinute() const
  2517. {
  2518.   AssertValid();
  2519.   return (WORD) ((m_dwTotalSeconds - (GetHour()*3600L))/60);
  2520. }
  2521.  
  2522. DWORD CLTimeOfDay::GetTotalSeconds() const
  2523. {
  2524.   AssertValid();
  2525.   return m_dwTotalSeconds;
  2526. }
  2527.  
  2528. WORD CLTimeOfDay::GetSecond() const
  2529. {
  2530.   AssertValid();
  2531.   return (WORD) (m_dwTotalSeconds - (60L * (GetMinute() + (60L*GetHour()))));
  2532. }                                                                
  2533.  
  2534. WORD CLTimeOfDay::GetAMPMHour() const
  2535. {
  2536.   AssertValid();
  2537.   WORD wHour = GetHour();
  2538.   if (wHour > 12)
  2539.     wHour -= 12;
  2540.   return wHour;
  2541. }                             
  2542.  
  2543. CString CLTimeOfDay::GetAMString()
  2544. {
  2545.   CString rVal;
  2546.   LPTSTR pszBuf = rVal.GetBuffer(20);
  2547.   int nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S1159, pszBuf, 20);
  2548.   rVal.ReleaseBuffer();
  2549.   return rVal;
  2550. }
  2551.  
  2552. CString CLTimeOfDay::GetPMString()
  2553. {
  2554.   CString rVal;
  2555.   LPTSTR pszBuf = rVal.GetBuffer(20);
  2556.   int nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S2359, pszBuf, 20);
  2557.   rVal.ReleaseBuffer();
  2558.   return rVal;
  2559. }
  2560.  
  2561. CString CLTimeOfDay::GetAMPMString() const
  2562. {
  2563.   AssertValid();
  2564.   if (GetHour() > 12)
  2565.     return GetPMString();
  2566.   else
  2567.     return GetAMString();
  2568. }
  2569.  
  2570. BOOL CLTimeOfDay::IsValid() const
  2571. {                  
  2572.   return m_bValid;
  2573. }
  2574.  
  2575. DWORD CLTimeOfDay::Collate() const
  2576. {
  2577.   AssertValid();
  2578.   DWORD rVal = GetHour()*10000L + GetMinute()*100L + GetSecond();
  2579.   return rVal;
  2580. }
  2581.  
  2582. SYSTEMTIME CLTimeOfDay::GetSYSTEMTIME() const
  2583. {
  2584.   AssertValid();
  2585.   SYSTEMTIME st;
  2586.  
  2587.   st.wYear=0;
  2588.   st.wMonth=0;
  2589.   st.wDayOfWeek=0;
  2590.   st.wDay=0;
  2591.   st.wHour = GetHour();
  2592.   st.wMinute = GetMinute();
  2593.   st.wSecond = GetSecond();
  2594.   st.wMilliseconds = 0;
  2595.   return st;
  2596. }
  2597.  
  2598. tm CLTimeOfDay::GetTM() const
  2599. {
  2600.   AssertValid();
  2601.   tm rVal;
  2602.   
  2603.   rVal.tm_hour  = GetHour();
  2604.   rVal.tm_min   = GetMinute();
  2605.   rVal.tm_sec   = GetSecond();
  2606.   rVal.tm_mday  = 0;
  2607.   rVal.tm_mon   = 0;
  2608.   rVal.tm_year  = 0;
  2609.   rVal.tm_wday  = 0;
  2610.   rVal.tm_yday  = 0;
  2611.   rVal.tm_isdst = 0;
  2612.               
  2613.   return rVal;
  2614. }
  2615.  
  2616. CLTimeOfDay& CLTimeOfDay::operator=(const CLTimeOfDay& Tod)
  2617. {               
  2618.   m_dwTotalSeconds = Tod.m_dwTotalSeconds;
  2619.   m_bValid = Tod.m_bValid;
  2620.   return *this;
  2621. }
  2622.  
  2623. CLTimeOfDay CLTimeOfDay::operator+(const CLTimeSpan& TimeSpan) const
  2624. {
  2625.   AssertValid();
  2626.   CLTimeSpan t = CLTimeSpan(*this) + CLTimeSpan(0, TimeSpan.GetHours(), TimeSpan.GetMinutes(),
  2627.                             TimeSpan.GetSeconds());
  2628.   return CLTimeOfDay(t.GetHours(), t.GetMinutes(), t.GetSeconds());
  2629. }
  2630.  
  2631. CLTimeOfDay CLTimeOfDay::operator-(const CLTimeSpan& TimeSpan) const
  2632. {
  2633.   AssertValid();
  2634.   //Addition of 1 Day is used to ensure result "t" does not go negative
  2635.   CLTimeSpan t = CLTimeSpan::OneDay() + CLTimeSpan(*this) - 
  2636.                  CLTimeSpan(0, TimeSpan.GetHours(), TimeSpan.GetMinutes(),
  2637.                             TimeSpan.GetSeconds());
  2638.   return CLTimeOfDay(t.GetHours(), t.GetMinutes(), t.GetSeconds());
  2639. }
  2640.  
  2641. CLTimeOfDay& CLTimeOfDay::operator+=(CLTimeSpan& TimeSpan)
  2642. {
  2643.   *this = *this + TimeSpan;
  2644.   return *this;
  2645. }
  2646.  
  2647. CLTimeOfDay& CLTimeOfDay::operator-=(CLTimeSpan& TimeSpan)
  2648. {
  2649.   *this = *this - TimeSpan;
  2650.   return *this;
  2651. }
  2652.  
  2653. BOOL CLTimeOfDay::operator==(const CLTimeOfDay& Tod) const
  2654. {
  2655.   AssertValid();
  2656.   return (m_dwTotalSeconds == Tod.m_dwTotalSeconds);
  2657. }
  2658.  
  2659. BOOL CLTimeOfDay::operator>(const CLTimeOfDay& Tod) const
  2660. {               
  2661.   AssertValid();
  2662.   return (m_dwTotalSeconds > Tod.m_dwTotalSeconds);
  2663. }
  2664.  
  2665. BOOL CLTimeOfDay::operator>=(const CLTimeOfDay& Tod) const
  2666. {               
  2667.   AssertValid();
  2668.   return (m_dwTotalSeconds >= Tod.m_dwTotalSeconds);
  2669. }
  2670.  
  2671. BOOL CLTimeOfDay::operator<(const CLTimeOfDay& Tod) const
  2672. {             
  2673.   AssertValid();
  2674.   return (m_dwTotalSeconds < Tod.m_dwTotalSeconds);
  2675. }
  2676.  
  2677. BOOL CLTimeOfDay::operator<=(const CLTimeOfDay& Tod) const
  2678. {
  2679.   AssertValid();
  2680.   return (m_dwTotalSeconds <= Tod.m_dwTotalSeconds);
  2681. }
  2682.  
  2683. BOOL CLTimeOfDay::operator!=(const CLTimeOfDay& Tod) const
  2684. {               
  2685.   AssertValid();                  
  2686.   return !operator==(Tod);
  2687. }
  2688.  
  2689. #ifdef _DEBUG
  2690. void CLTimeOfDay::AssertValid() const
  2691. {
  2692.   CObject::AssertValid();
  2693.   ASSERT(IsValid());
  2694. }
  2695. #endif
  2696.  
  2697. #ifdef _DEBUG
  2698. void CLTimeOfDay::Dump(CDumpContext& dc) const
  2699. {
  2700.   CObject::Dump(dc);
  2701.   if (IsValid())
  2702.     dc << Format() << _T("\n");
  2703.   else
  2704.     dc << _T("Invalid state\n");
  2705. }
  2706. #endif                       
  2707.  
  2708. /*    //The Following Format parameters are supported        
  2709.  
  2710. %H    Hours in the current day
  2711. %M    Minutes in the current hour
  2712. %h    12 Hour format Hours in this CLTimeSpan (00 - 12)
  2713. %P    AM / PM indicator
  2714. %S    Seconds in the current minute
  2715. %%    Percent sign       
  2716. %x    Time Of Day representation for current locale        
  2717. %#H, %#h, %#M, %#S  Remove leading zeros (if any).
  2718. */
  2719. CString CLTimeOfDay::Format(const CString& sFormat) const
  2720.   CString rVal;
  2721.   if (IsValid())
  2722.   {
  2723.     CString sBuffer;
  2724.     int sFmtLength = sFormat.GetLength();
  2725.  
  2726.     for (int i=0; i<sFmtLength; i++)
  2727.     {
  2728.       TCHAR c = sFormat.GetAt(i);
  2729.       if (c == _T('%'))
  2730.       {
  2731.         ++i;
  2732.         if (i < sFmtLength)
  2733.         {
  2734.           c = sFormat.GetAt(i);
  2735.           switch (c)
  2736.           {
  2737.             case _T('H'):
  2738.             {
  2739.               sBuffer.Format(_T("%.02d"), GetHour());
  2740.               rVal += sBuffer;
  2741.               break;
  2742.             }
  2743.             case _T('M'):
  2744.             {
  2745.               sBuffer.Format(_T("%.02d"), GetMinute());
  2746.               rVal += sBuffer;
  2747.               break;
  2748.             }
  2749.             case _T('h'):
  2750.             {
  2751.               sBuffer.Format(_T("%.02d"), GetAMPMHour());
  2752.               rVal += sBuffer;
  2753.               break;
  2754.             }
  2755.             case _T('P'):
  2756.             {
  2757.               rVal += GetAMPMString();
  2758.               break;
  2759.             }
  2760.             case _T('S'):
  2761.             {
  2762.               sBuffer.Format(_T("%.02d"), GetSecond());
  2763.               rVal += sBuffer;
  2764.               break;
  2765.             }
  2766.             case _T('x'):                                      
  2767.             {
  2768.               sBuffer.Empty();
  2769.               SYSTEMTIME st = GetSYSTEMTIME();
  2770.               int Res = ::GetTimeFormat(LOCALE_USER_DEFAULT,
  2771.                                       LOCALE_NOUSEROVERRIDE,
  2772.                                       &st,
  2773.                                       NULL,
  2774.                                       sBuffer.GetBufferSetLength(100),
  2775.                                       100); 
  2776.               if (Res == 0)
  2777.                 TRACE1("GetDateFormat() Failed in CLTimeSpan::Format(), GetLastError() returned %ul\n", ::GetLastError());
  2778.               sBuffer.ReleaseBuffer();
  2779.               rVal += sBuffer;
  2780.               break;
  2781.             }
  2782.             case _T('#'):
  2783.             {
  2784.               if (i < sFmtLength)
  2785.               {
  2786.                 ++i;
  2787.                 c = sFormat.GetAt(i);
  2788.                 switch (c)
  2789.                 {
  2790.                   case _T('H'):
  2791.                   {
  2792.                     sBuffer.Format(_T("%d"), GetHour());
  2793.                     rVal += sBuffer;
  2794.                     break;
  2795.                   }
  2796.                   case _T('h'):
  2797.                   {
  2798.                     sBuffer.Format(_T("%d"), GetAMPMHour());
  2799.                     rVal += sBuffer;
  2800.                     break;
  2801.                   }
  2802.                   case _T('M'):
  2803.                   {
  2804.                     sBuffer.Format(_T("%d"), GetMinute());
  2805.                     rVal += sBuffer;
  2806.                     break;
  2807.                   }
  2808.                   case _T('S'):
  2809.                   {
  2810.                     sBuffer.Format(_T("%d"), GetSecond());
  2811.                     rVal += sBuffer;
  2812.                     break;
  2813.                   }
  2814.                   default:
  2815.                   {
  2816.                     rVal += c;
  2817.                     break;
  2818.                   }
  2819.                 }
  2820.               }
  2821.               break;
  2822.             }
  2823.             default:
  2824.             {
  2825.               rVal += c;
  2826.               break;
  2827.             }
  2828.           }
  2829.         }
  2830.       }
  2831.       else
  2832.       {
  2833.         rVal += c;
  2834.       }
  2835.     }
  2836.   }
  2837.   return rVal;
  2838. }
  2839.  
  2840. //Format according to the time format as specified by the control panel
  2841. CString CLTimeOfDay::Format(DWORD dwFlags) const
  2842. {
  2843.   if (dwFlags & DTF_NOSECOND)
  2844.     return Format(sm_sDefaultFormatNOS);
  2845.   else
  2846.     return Format(sm_sDefaultFormat);
  2847. }
  2848.  
  2849. void CLTimeOfDay::GetDefaultFormat()
  2850. {
  2851.   CString sBuf;
  2852.  
  2853.   // Is there to be a leading 0 on the Hour?
  2854.   BOOL bHourLZ = FALSE;
  2855.   LPTSTR pszBuf = sBuf.GetBuffer(10);
  2856.   int nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, pszBuf, 10);
  2857.   ASSERT(nChars);
  2858.   sBuf.ReleaseBuffer();
  2859.   if (sBuf == _T("0"))  //No leading zeros for hours
  2860.     bHourLZ = FALSE;
  2861.   else if (sBuf == _T("1"))  //Leading zeros for hours
  2862.     bHourLZ = TRUE;
  2863.   else
  2864.     ASSERT(FALSE);
  2865.  
  2866.   // Get the time separator character
  2867.   CString sSep(_T(":"));
  2868.   pszBuf = sSep.GetBuffer(10);
  2869.   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, pszBuf, 10);
  2870.   ASSERT(nChars);
  2871.   sSep.ReleaseBuffer();
  2872.  
  2873.   //Get the 24 Hour / 12 Hour indicator
  2874.   BOOL b24Hour = FALSE;
  2875.   pszBuf = sBuf.GetBuffer(10);
  2876.   nChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, pszBuf, 10);
  2877.   ASSERT(nChars);
  2878.   sBuf.ReleaseBuffer();
  2879.   if (sBuf == _T("0"))  //AM / PM Style
  2880.     b24Hour = FALSE;
  2881.   else if (sBuf == _T("1"))  //24 Hour Style
  2882.     b24Hour = TRUE;
  2883.   else
  2884.     ASSERT(FALSE);
  2885.  
  2886.  
  2887.   //Modify behaviour depending on the various flags
  2888.   if (bHourLZ)
  2889.   {
  2890.     if (b24Hour)
  2891.     {
  2892.       sm_sDefaultFormatNOS.Format(_T("%%H%s%%M"), sSep);
  2893.       sm_sDefaultFormat.Format(_T("%%H%s%%M%s%%S"), sSep, sSep);
  2894.     }
  2895.     else
  2896.     {
  2897.       sm_sDefaultFormatNOS.Format(_T("%%h%s%%M %%P"), sSep);
  2898.       sm_sDefaultFormat.Format(_T("%%h%s%%M%s%%S %%P"), sSep, sSep);
  2899.     }
  2900.   }
  2901.   else
  2902.   {
  2903.     if (b24Hour)
  2904.     {
  2905.       sm_sDefaultFormatNOS.Format(_T("%%#H%s%%M"), sSep, sSep);
  2906.       sm_sDefaultFormat.Format(_T("%%#H%s%%M%s%%S"), sSep, sSep, sSep);
  2907.     }
  2908.     else
  2909.     {
  2910.       sm_sDefaultFormatNOS.Format(_T("%%#h%s%%M %%P"), sSep, sSep);
  2911.       sm_sDefaultFormat.Format(_T("%%#h%s%%M%s%%S %%P"), sSep, sSep, sSep);
  2912.     }
  2913.   }
  2914. }
  2915.  
  2916. void CLTimeOfDay::Serialize(CArchive& ar)
  2917. {
  2918.   CObject::Serialize(ar);
  2919.  
  2920.   if (ar.IsStoring())
  2921.   {
  2922.     ar << m_dwTotalSeconds;
  2923.     ar << m_bValid;
  2924.   }
  2925.   else
  2926.   {
  2927.     ar >> m_dwTotalSeconds;
  2928.     ar >> m_bValid;
  2929.   }
  2930. }
  2931.  
  2932. ostream& operator<<(ostream &os, const CLTimeOfDay &TimeOfDay)
  2933. {
  2934.   return os << TimeOfDay.Format();
  2935. }                       
  2936.  
  2937. CArchive& operator<<(CArchive& ar, CLTimeOfDay &TimeOfDay)
  2938. {
  2939.   ASSERT(ar.IsStoring());
  2940.   TimeOfDay.Serialize(ar);
  2941.   return ar;
  2942. }
  2943.  
  2944. CArchive& operator>>(CArchive& ar, CLTimeOfDay &TimeOfDay)
  2945. {
  2946.   ASSERT(!ar.IsStoring());
  2947.   TimeOfDay.Serialize(ar);
  2948.   return ar;
  2949. }
  2950.  
  2951.  
  2952.  
  2953.  
  2954.  
  2955.  
  2956. //CLDate implementation
  2957.  
  2958.  
  2959. CLDate::CLDate()
  2960. {
  2961.   Set();
  2962. }
  2963.   
  2964. CLDate::CLDate(LONG Year, WORD Month, WORD Day, 
  2965.                WORD Hour, WORD Minute, WORD Second,
  2966.                TimeFrame tf)
  2967. {
  2968.   Set(Year, Month, Day, Hour, Minute, Second, tf);
  2969. }                                            
  2970.  
  2971. CLDate::CLDate(const SYSTEMTIME& st, TimeFrame tf, BOOL bUseDayOfWeek)
  2972.   Set(st, tf, bUseDayOfWeek);
  2973.  
  2974. CLDate::CLDate(LONG Year, WORD Month, WORD WeekOfMonth,
  2975.                WORD DayOfWeek, WORD Hour, WORD Minute, WORD Second,
  2976.                TimeFrame tf)
  2977. {
  2978.   Set(Year, Month, WeekOfMonth, DayOfWeek, Hour, Minute, Second, tf);
  2979. }
  2980.                
  2981. CLDate::CLDate(LONG Days, CDate::DateEpoch e, WORD Hour, WORD Minute,
  2982.                WORD Second, TimeFrame tf)
  2983. {
  2984.   Set(Days, e, Hour, Minute, Second, tf);
  2985.  
  2986. CLDate::CLDate(const CDate& Date, const CLTimeOfDay& Tod, TimeFrame tf)
  2987.   Set(Date, Tod, tf);
  2988. }
  2989.  
  2990.  
  2991. CLDate::CLDate(const CLDate& ld)
  2992. {                                 
  2993.   m_nSeconds  = ld.m_nSeconds;
  2994.   m_bValid    = ld.m_bValid;
  2995.   m_TimeFrame = ld.m_TimeFrame;
  2996. }
  2997.  
  2998. CLDate::CLDate(const CTime& ct)
  2999. {
  3000.   Set(ct);
  3001. }
  3002.       
  3003. CLDate::CLDate(const COleDateTime& oleTime, TimeFrame tf)
  3004. {
  3005.   Set(oleTime, tf);
  3006. }                     
  3007.  
  3008. CLDate& CLDate::Set()
  3009. {
  3010.   m_nSeconds = 0;
  3011.   m_bValid = FALSE;
  3012.   return *this;
  3013. }
  3014.  
  3015. CLDate& CLDate::Set(LONG Year, WORD Month, WORD Day,
  3016.                     WORD Hour, WORD Minute, WORD Second,
  3017.                     TimeFrame tf)
  3018. {              
  3019.   CDate Date(Year, Month, Day);
  3020.   CLTimeOfDay Tod(Hour, Minute, Second);
  3021.  
  3022.   m_TimeFrame = tf;
  3023.   m_nSeconds = __int64(Date.GetValue())*86400 + Tod.GetTotalSeconds();
  3024.   m_bValid = TRUE;
  3025.  
  3026.   if (tf == LOCAL)
  3027.     CheckForValidLocalDate();
  3028.   return *this;
  3029. }
  3030.                     
  3031. CLDate& CLDate::Set(const SYSTEMTIME& st, TimeFrame tf, BOOL bUseDayOfWeek)
  3032. {
  3033.   if (bUseDayOfWeek)  //Using Day-in-month format
  3034.   {
  3035.     if (st.wYear)     //an absolute year, wDayOfWeek is 0 based
  3036.       Set(st.wYear, st.wMonth, st.wDay, (WORD)(st.wDayOfWeek+1), st.wHour, 
  3037.           st.wMinute, st.wSecond, tf);
  3038.     else              //use the current year
  3039.       Set(CurrentTime(tf).GetCDate().GetYear(), st.wMonth, st.wDay, 
  3040.           (WORD)(st.wDayOfWeek+1), st.wHour, st.wMinute, st.wSecond, tf);
  3041.   }
  3042.   else
  3043.   {
  3044.     if (st.wYear)     //an absolute year
  3045.       Set(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, tf);
  3046.     else              //use the current year
  3047.       Set(CurrentTime(tf).GetCDate().GetYear(), st.wMonth, st.wDay, 
  3048.           st.wHour, st.wMinute, st.wSecond, tf);
  3049.   }
  3050.  
  3051.   return *this;
  3052. }
  3053.  
  3054.  
  3055. CLDate& CLDate::Set(LONG Year, WORD Month, WORD WeekOfMonth, 
  3056.                     WORD DayOfWeek, WORD Hour, WORD Minute, WORD Second,
  3057.                     TimeFrame tf)
  3058. {
  3059.   CDate Date(Year, Month, WeekOfMonth, DayOfWeek);
  3060.   CLTimeOfDay Tod(Hour, Minute, Second);
  3061.  
  3062.   m_TimeFrame = tf;
  3063.   m_nSeconds = __int64(Date.GetValue())*86400 + Tod.GetTotalSeconds();
  3064.   m_bValid = TRUE;
  3065.  
  3066.   if (tf == LOCAL)
  3067.     CheckForValidLocalDate();
  3068.   return *this;
  3069. }
  3070.                     
  3071. CLDate& CLDate::Set(LONG Days, CDate::DateEpoch e, WORD Hour, WORD Minute,
  3072.                     WORD Second, TimeFrame tf)
  3073. {
  3074.   CDate Date(Days, e);
  3075.   CLTimeOfDay Tod(Hour, Minute, Second);
  3076.  
  3077.   m_TimeFrame = tf;
  3078.   m_nSeconds = __int64(Date.GetValue())*86400 + Tod.GetTotalSeconds();
  3079.   m_bValid = TRUE;
  3080.  
  3081.   if (tf == LOCAL)
  3082.     CheckForValidLocalDate();
  3083.   return *this;
  3084. }
  3085.  
  3086. CLDate& CLDate::Set(const CTime& ct)
  3087. {
  3088.   m_TimeFrame = UCT;
  3089.   tm* pTM = ct.GetGmtTm();
  3090.   Set(pTM->tm_year + 1900, (WORD) (pTM->tm_mon+1), (WORD) pTM->tm_mday, 
  3091.          (WORD) pTM->tm_hour, (WORD) pTM->tm_min, (WORD) pTM->tm_sec, UCT);
  3092.   return *this;  
  3093. }
  3094.  
  3095. CLDate& CLDate::Set(const CDate& Date, const CLTimeOfDay& Tod, TimeFrame tf)
  3096. {
  3097.   if (!Date.IsValid() || !Tod.IsValid())
  3098.     Set();
  3099.   else
  3100.   {
  3101.     m_TimeFrame = tf;
  3102.     m_nSeconds = __int64(Date.GetValue())*86400 + Tod.GetTotalSeconds();
  3103.     m_bValid = TRUE;
  3104.  
  3105.     if (tf == LOCAL)
  3106.       CheckForValidLocalDate();
  3107.   }
  3108.  
  3109.   return *this;  
  3110. }
  3111.       
  3112. CLDate& CLDate::Set(const COleDateTime& oleTime, TimeFrame tf)
  3113. {
  3114.   COleDateTime::DateTimeStatus dts(oleTime.GetStatus());
  3115.   if (dts == COleDateTime::DateTimeStatus::valid)
  3116.     Set((LONG) oleTime.GetYear(), (WORD) oleTime.GetMonth(), (WORD) oleTime.GetDay(),
  3117.         (WORD) oleTime.GetHour(), (WORD) oleTime.GetMinute(), (WORD) oleTime.GetSecond(), tf);
  3118.   else
  3119.     Set();
  3120.   return *this;
  3121. }                     
  3122.  
  3123. void CLDate::CheckForValidLocalDate()
  3124. {
  3125.   //Should only be called when tested a LOCAL CLDate
  3126.   ASSERT(m_TimeFrame == LOCAL);
  3127.  
  3128.   TIME_ZONE_INFORMATION tzi;
  3129.   BOOL bSuccess = (::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  3130.   ASSERT(bSuccess);
  3131.   
  3132.   //Set the TimeFrame to UCT so that we do not need to perform DST conversions in
  3133.   //the following arithmetic
  3134.   m_TimeFrame = UCT;
  3135.  
  3136.   CLDate BeginDaylightTime;
  3137.   LONG ThisYear = GetCDate().GetYear();
  3138.   if (tzi.DaylightDate.wYear == 0)  //Using Day-in-month format
  3139.     BeginDaylightTime.Set(ThisYear, tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay, (WORD)(tzi.DaylightDate.wDayOfWeek+1),
  3140.                           tzi.DaylightDate.wHour, tzi.DaylightDate.wMinute, tzi.DaylightDate.wSecond, UCT);
  3141.   else
  3142.     BeginDaylightTime.Set(tzi.DaylightDate.wYear, tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay, tzi.DaylightDate.wHour,
  3143.                           tzi.DaylightDate.wMinute, tzi.DaylightDate.wSecond, UCT);
  3144.  
  3145.   CLDate BeginStandardTime;
  3146.   if (tzi.StandardDate.wYear == 0)  //Using Day-in-month format
  3147.     BeginStandardTime.Set(ThisYear, tzi.StandardDate.wMonth, tzi.StandardDate.wDay, (WORD)(tzi.StandardDate.wDayOfWeek+1),
  3148.                           tzi.StandardDate.wHour, tzi.StandardDate.wMinute, tzi.StandardDate.wSecond, UCT);
  3149.   else
  3150.     BeginStandardTime.Set(tzi.StandardDate.wYear, tzi.StandardDate.wMonth, tzi.StandardDate.wDay, tzi.StandardDate.wHour, 
  3151.                           tzi.StandardDate.wMinute, tzi.StandardDate.wSecond, UCT);
  3152.  
  3153.  
  3154. #ifdef _DEBUG
  3155.   CString s = BeginDaylightTime.Format();
  3156.   s = BeginStandardTime.Format();
  3157. #endif
  3158.  
  3159.   if (tzi.DaylightBias > 0)
  3160.   {
  3161.     //A CLDate which specifies a date which occurs twice
  3162.     CLDate StartNonUnique(BeginDaylightTime - CLTimeSpan(0, 0, (WORD) tzi.DaylightBias, 0));
  3163.     if ((*this >= StartNonUnique) && (*this < BeginDaylightTime))
  3164.     {
  3165.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which represents a non unique absolute time\n"); 
  3166.       if (sm_bDoAsserts)
  3167.         ASSERT(FALSE);
  3168.       Set();
  3169.       return;
  3170.     }
  3171.  
  3172.     //A CLDate which specifies a date which does not occur
  3173.     CLDate EndSkip(BeginStandardTime + CLTimeSpan(0, 0, (WORD) tzi.DaylightBias, 0));
  3174.     if ((*this > BeginStandardTime) && (*this < EndSkip))
  3175.     {
  3176.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which does not occur\n");
  3177.       if (sm_bDoAsserts)
  3178.         ASSERT(FALSE);
  3179.       Set();
  3180.       return;
  3181.     }
  3182.  
  3183.   }
  3184.   else if (tzi.DaylightBias < 0)
  3185.   {
  3186.     //A CLDate which specifies a date which does not occur
  3187.     CLDate EndSkip(BeginDaylightTime + CLTimeSpan(0, 0, (WORD) -tzi.DaylightBias, 0));
  3188.     if ((*this > BeginDaylightTime) && (*this < EndSkip))
  3189.     {
  3190.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which does not occur\n"); 
  3191.       if (sm_bDoAsserts)
  3192.         ASSERT(FALSE);
  3193.       Set();
  3194.       return;
  3195.     }
  3196.  
  3197.     //A CLDate which specifies a date which occurs twice
  3198.     CLDate StartNonUnique(BeginStandardTime - CLTimeSpan(0, 0, (WORD) -tzi.DaylightBias, 0));
  3199.     if ((*this >= StartNonUnique) && 
  3200.         (*this <= BeginStandardTime) )
  3201.     {
  3202.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which represents a non unique absolute time\n"); 
  3203.       if (sm_bDoAsserts)
  3204.         ASSERT(FALSE);
  3205.       Set();
  3206.       return;
  3207.     }
  3208.   }
  3209.  
  3210.   //return the timeframe back to local
  3211.   m_TimeFrame = LOCAL;
  3212. }
  3213.                     
  3214. CLDate CLDate::CurrentTime(TimeFrame tf)
  3215. {                                      
  3216.   SYSTEMTIME st;
  3217.   ::GetSystemTime(&st);
  3218.   CLDate rVal(st, UCT);
  3219.   rVal.SetTimeFrame(tf);
  3220.   return rVal; 
  3221. }
  3222.  
  3223. CLTimeSpan CLDate::DeltaT(CLDate& d)
  3224. {
  3225.   CLTimeSpan Tspan(d - CLDate(CDate::Epoch2000(), CLTimeOfDay(0, 0, 0), d.GetTimeFrame()));
  3226.   double T = Tspan.GetTotalDays()/36525.0;
  3227.   double S;
  3228.  
  3229.   double y = 2000 + T * 100;
  3230.   if (y > 2000)
  3231.     S = 102.3 + T * (123.5 + T * 32.5);
  3232.   else if (y < 1620)
  3233.   {
  3234.     if (y < 948)
  3235.       S = 2715.6 + T * (573.36 + T * 46.5);
  3236.     else 
  3237.       S = 50.6 + T * (67.5 + T * 22.5);
  3238.   }
  3239.   else /* Interpolate from the static data table */
  3240.   {
  3241.     int Index = (int)((y - 1620) / 2);
  3242.     if (Index > 185)
  3243.       Index = 185;
  3244.     y = y / 2 - Index - 810;
  3245.     S = (DeltaTTable[Index] + (DeltaTTable[Index + 1] - DeltaTTable[Index]) * y) / 10;
  3246.   }
  3247.  
  3248.   return CLTimeSpan(S);
  3249. }
  3250.  
  3251. BOOL CLDate::CurrentlyInDST()
  3252. {
  3253.   TIME_ZONE_INFORMATION tzi;
  3254.   return ::GetTimeZoneInformation(&tzi) == TIME_ZONE_ID_DAYLIGHT;
  3255. }
  3256.  
  3257. CLTimeSpan CLDate::DaylightBias()
  3258. {
  3259.   TIME_ZONE_INFORMATION tzi;
  3260.   BOOL bSuccess = (::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  3261.   ASSERT(bSuccess);
  3262.  
  3263.   CLTimeSpan rVal;
  3264.   if (tzi.DaylightBias > 0)
  3265.     rVal = CLTimeSpan(0, 0, (WORD) tzi.DaylightBias, 0);
  3266.   else
  3267.   {
  3268.     rVal = CLTimeSpan(0, 0, (WORD) -tzi.DaylightBias, 0);
  3269.     rVal.Negate();
  3270.   }
  3271.   return rVal;
  3272. }
  3273.  
  3274. CLTimeSpan CLDate::TimezoneBias()
  3275. {
  3276.   TIME_ZONE_INFORMATION tzi;
  3277.   BOOL bSuccess = (::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  3278.   ASSERT(bSuccess);
  3279.  
  3280.   CLTimeSpan rVal;
  3281.   LONG tzBias = tzi.StandardBias + tzi.Bias;
  3282.   if (tzBias > 0)
  3283.     rVal = CLTimeSpan(0, 0, (WORD) tzBias, 0);
  3284.   else
  3285.   {
  3286.     rVal = CLTimeSpan(0, 0, (WORD) -tzBias, 0);
  3287.     rVal.Negate();
  3288.   }
  3289.   return rVal;
  3290. }
  3291.  
  3292. CString CLDate::DaylightName()
  3293. {
  3294.   TIME_ZONE_INFORMATION tzi;
  3295.   BOOL bSuccess = (::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  3296.   ASSERT(bSuccess);
  3297.   return tzi.DaylightName;
  3298. }
  3299.  
  3300. CString CLDate::StandardName()
  3301. {
  3302.   TIME_ZONE_INFORMATION tzi;
  3303.   BOOL bSuccess = (::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  3304.   ASSERT(bSuccess);
  3305.   return tzi.StandardName;
  3306. }
  3307.  
  3308. #ifdef _DEBUG
  3309. BOOL CLDate::SetDoConstructorAsserts(BOOL bDoAsserts)
  3310. {
  3311.   BOOL bOldDoAsserts = sm_bDoAsserts;
  3312.   sm_bDoAsserts = bDoAsserts;
  3313.   return bOldDoAsserts;
  3314. }
  3315. #endif            
  3316.  
  3317. CDate CLDate::GetCDate() const
  3318. {
  3319.   CDate rVal;
  3320.   if (IsValid())
  3321.     rVal = CDate(((LONG) (m_nSeconds/86400))-2000000000L, CDate::EPOCH_GREG);
  3322.  
  3323.   return rVal;
  3324. }
  3325.  
  3326. CLTimeOfDay CLDate::GetCLTimeOfDay() const
  3327. {
  3328.   CLTimeOfDay rVal;
  3329.   if (IsValid())
  3330.   {
  3331.     __int64 nSeconds = m_nSeconds - __int64(GetCDate().GetValue())*86400;
  3332.     rVal = CLTimeOfDay((DWORD) nSeconds);
  3333.   }
  3334.   return rVal;
  3335. }
  3336.  
  3337. DateLS CLDate::GetDate() const
  3338. {
  3339.   DateLS rVal;
  3340.   DateS ds = GetCDate().GetDate();
  3341.  
  3342.   rVal.lYear = ds.lYear; 
  3343.   rVal.wMonth = ds.wMonth;
  3344.   rVal.wDay = ds.wDay;
  3345.   rVal.wWday = ds.wWday;
  3346.   rVal.wYday = ds.wYday;
  3347.   rVal.ct = ds.ct;
  3348.   rVal.tf = m_TimeFrame;
  3349.   CLTimeOfDay tod(GetCLTimeOfDay());
  3350.   rVal.wHour = tod.GetHour();
  3351.   rVal.wMinute = tod.GetMinute();
  3352.   rVal.wSecond = tod.GetSecond();
  3353.   
  3354.   return rVal;
  3355. };
  3356.  
  3357. SYSTEMTIME CLDate::GetSYSTEMTIME() const
  3358. {
  3359.   SYSTEMTIME s = GetCDate().GetSYSTEMTIME();
  3360.   CLTimeOfDay tod(GetCLTimeOfDay());
  3361.  
  3362.   s.wHour = tod.GetHour();
  3363.   s.wMinute = tod.GetMinute();
  3364.   s.wSecond = tod.GetSecond();
  3365.   s.wMilliseconds = 0;
  3366.  
  3367.   return s;
  3368. }                         
  3369.  
  3370. tm CLDate::GetTM()
  3371. {
  3372.   AssertValid();
  3373.  
  3374.   tm rVal;                
  3375.   rVal.tm_sec   = 0;
  3376.   rVal.tm_min   = 0;
  3377.   rVal.tm_hour  = 0;
  3378.   rVal.tm_mday  = 0;
  3379.   rVal.tm_mon   = 0;
  3380.   rVal.tm_year  = 0;
  3381.   rVal.tm_wday  = 0;
  3382.   rVal.tm_yday  = 0;
  3383.   rVal.tm_isdst = 0;
  3384.  
  3385.   DateLS ds = GetDate();
  3386.  
  3387.   long MinYear = 1900L + LONG_MIN;
  3388.   long MaxYear = LONG_MAX;
  3389.  
  3390.   //handle range errors
  3391.   if ((ds.lYear < MinYear) || (ds.lYear > MaxYear))
  3392.   {
  3393.     ASSERT(FALSE);
  3394.     return rVal;
  3395.   }
  3396.   
  3397.   rVal.tm_hour = ds.wHour;
  3398.   rVal.tm_min = ds.wMinute;
  3399.   rVal.tm_sec = ds.wSecond;
  3400.   rVal.tm_year = (int) (ds.lYear - 1900L);
  3401.   rVal.tm_mon = ds.wMonth - 1;  //tm struct uses 0 based indices
  3402.   rVal.tm_wday = ds.wWday - 1;  //tm struct uses 0 based indices
  3403.   rVal.tm_mday = ds.wDay;
  3404.   rVal.tm_wday = ds.wYday - 1; //Returns days since Jan 1
  3405.   rVal.tm_isdst = IsDST();
  3406.               
  3407.   return rVal;
  3408. }
  3409.  
  3410. TimeFrame CLDate::GetTimeFrame() const
  3411. {
  3412.   AssertValid();
  3413.   return m_TimeFrame;
  3414. }
  3415.  
  3416. TimeFrame CLDate::SetTimeFrame(TimeFrame tf)
  3417. {
  3418.   if (tf == m_TimeFrame)  //quick return
  3419.     return tf;
  3420.     
  3421.   TimeFrame OldTF = m_TimeFrame;   
  3422.  
  3423.   switch (m_TimeFrame)
  3424.   {
  3425.     case LOCAL:
  3426.     {
  3427.       switch (tf)
  3428.       {
  3429.         case UCT:
  3430.         {
  3431.           //pretend that timeframe is UCT to avoid recursion in the arithmetic
  3432.           m_TimeFrame = UCT;
  3433.  
  3434.           *this += TimezoneBias();
  3435.           if (DST())
  3436.             *this += DaylightBias();
  3437.           break;
  3438.         }
  3439.         case ET:
  3440.         {
  3441.           SetTimeFrame(UCT);
  3442.           SetTimeFrame(ET);
  3443.           break;
  3444.         }
  3445.         default: ASSERT(FALSE);
  3446.       }
  3447.       break;
  3448.     }
  3449.     case ET:
  3450.     {
  3451.       switch (tf)
  3452.       {
  3453.         case UCT:
  3454.         {
  3455.           *this -= DeltaT();
  3456.           break;
  3457.         }
  3458.         case LOCAL:
  3459.         {
  3460.           SetTimeFrame(UCT);
  3461.           SetTimeFrame(LOCAL);
  3462.           break;
  3463.         }
  3464.         default: ASSERT(FALSE);
  3465.       }
  3466.       break;
  3467.     }
  3468.     case UCT:
  3469.     {
  3470.       switch (tf)
  3471.       {
  3472.         case LOCAL:
  3473.         {
  3474.           *this -= TimezoneBias();
  3475.           if (DST())
  3476.           {
  3477.             *this -= DaylightBias();
  3478.             sm_bIsDst = TRUE;
  3479.           }
  3480.           else
  3481.             sm_bIsDst = FALSE;
  3482.           break;
  3483.         }
  3484.         case ET:
  3485.         {
  3486.           *this += DeltaT();
  3487.           break;
  3488.         }
  3489.         default: ASSERT(FALSE);
  3490.       }
  3491.       break;
  3492.     }
  3493.  
  3494.     default: ASSERT(FALSE);
  3495.   }
  3496.  
  3497.   m_TimeFrame = tf;
  3498.   return OldTF;
  3499. };
  3500.  
  3501. BOOL CLDate::IsDST()
  3502. {
  3503.   AssertValid();
  3504.   BOOL rVal;  
  3505.   TimeFrame OldTF = GetTimeFrame();
  3506.   if (OldTF != LOCAL)
  3507.   {
  3508.     SetTimeFrame(LOCAL);
  3509.     rVal = sm_bIsDst;
  3510.   }
  3511.   else
  3512.     rVal = DST();
  3513.   return rVal;
  3514. }
  3515.  
  3516. BOOL CLDate::DST()
  3517. {
  3518.   AssertValid();
  3519.   BOOL rVal = TRUE;
  3520.   TIME_ZONE_INFORMATION tzi;
  3521.   DWORD dwTZI = ::GetTimeZoneInformation(&tzi);
  3522.   ASSERT(dwTZI != TIME_ZONE_ID_UNKNOWN);
  3523.  
  3524.   long lYear = GetCDate().GetYear();
  3525.  
  3526.   //SYSTEMTIME can only accomadate a WORD sized year
  3527.   //so we always return FALSE if outside of this range
  3528.   if ((lYear > SHRT_MAX) || (lYear < 0))
  3529.     rVal = FALSE;
  3530.  
  3531.   if (rVal)
  3532.   {
  3533.     TimeFrame OldTF = m_TimeFrame;
  3534.     m_TimeFrame = UCT;
  3535.  
  3536.     BOOL bUseDayOfWeek = FALSE;
  3537.     if (tzi.DaylightDate.wYear == 0)
  3538.     {
  3539.       bUseDayOfWeek = TRUE;
  3540.       tzi.DaylightDate.wYear = (WORD) lYear;
  3541.     }
  3542.  
  3543.     CLDate BeginDST(tzi.DaylightDate, UCT, bUseDayOfWeek);
  3544.  
  3545. #ifdef _DEBUG
  3546.     CString s = BeginDST.Format();
  3547. #endif
  3548.  
  3549.     bUseDayOfWeek = FALSE;
  3550.     if (tzi.StandardDate.wYear == 0)
  3551.     {
  3552.       bUseDayOfWeek = TRUE;
  3553.       tzi.StandardDate.wYear = (WORD) lYear;
  3554.     }
  3555.  
  3556.     CLDate EndDST(tzi.StandardDate, UCT, bUseDayOfWeek);
  3557. #ifdef _DEBUG
  3558.     s = EndDST.Format();
  3559. #endif
  3560.   
  3561.     rVal = rVal && (*this >= BeginDST && *this < EndDST);
  3562.  
  3563.     m_TimeFrame = OldTF;
  3564.   }
  3565.   
  3566.   return rVal;
  3567. }
  3568.  
  3569. CString CLDate::GetStringTimeFrame() const
  3570. {
  3571.   CString rVal;
  3572.   switch (m_TimeFrame)
  3573.   {
  3574.     case UCT:   
  3575.       if (!rVal.LoadString(IDS_UCT))
  3576.         ASSERT(FALSE);
  3577.       break;
  3578.     case ET:  
  3579.       if (!rVal.LoadString(IDS_ET))
  3580.         ASSERT(FALSE);
  3581.       break;
  3582.     case LOCAL: 
  3583.       if (!rVal.LoadString(IDS_LOCAL))
  3584.         ASSERT(FALSE);
  3585.       break;
  3586.     default:  
  3587.       ASSERT(FALSE);
  3588.       break;
  3589.   }
  3590.   return rVal;
  3591. }
  3592.  
  3593. void CLDate::AddYear(int Years)
  3594. {
  3595.   AssertValid();
  3596.   CDate Date(GetCDate());
  3597.   CLTimeOfDay Tod(GetCLTimeOfDay());
  3598.   Date.AddYear(Years);
  3599.   Set(Date, Tod, m_TimeFrame);
  3600. }
  3601.  
  3602. void CLDate::AddMonth(int Months)
  3603. {
  3604.   AssertValid();
  3605.   CDate Date(GetCDate());
  3606.   CLTimeOfDay Tod(GetCLTimeOfDay());
  3607.   Date.AddMonth(Months);
  3608.   Set(Date, Tod, m_TimeFrame);
  3609. }
  3610.  
  3611. void CLDate::AddWeek(int Weeks)
  3612. {
  3613.   AssertValid();
  3614.  
  3615.   CDate Date(GetCDate());
  3616.   CLTimeOfDay Tod(GetCLTimeOfDay());
  3617.   Date.AddWeek(Weeks);
  3618.   Set(Date, Tod, m_TimeFrame);
  3619. }
  3620.  
  3621. BOOL CLDate::IsValid() const
  3622. {
  3623.   return m_bValid;
  3624. }
  3625.  
  3626. CLTimeSpan CLDate::DeltaT()
  3627. {
  3628.   AssertValid();
  3629.   return DeltaT(*this);
  3630. }
  3631.  
  3632. CLDate& CLDate::operator=(const CLDate& d) 
  3633. {
  3634.   m_TimeFrame = d.m_TimeFrame;
  3635.   m_nSeconds = d.m_nSeconds;
  3636.   m_bValid = d.m_bValid;
  3637.   return *this;
  3638. }              
  3639.  
  3640. CLDate CLDate::operator+(const CLTimeSpan& TimeSpan)
  3641. {
  3642.   AssertValid();
  3643.   TimeSpan.AssertValid();
  3644.  
  3645.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3646.   TimeFrame OldTF = GetTimeFrame();
  3647.   if (GetTimeFrame() == LOCAL)
  3648.     SetTimeFrame(UCT);
  3649.  
  3650.   CLDate rVal;
  3651.   rVal.m_nSeconds = m_nSeconds + TimeSpan.m_nSeconds;
  3652.   rVal.m_TimeFrame = m_TimeFrame;
  3653.   rVal.m_bValid = TRUE;
  3654.  
  3655.   SetTimeFrame(OldTF);
  3656.   rVal.SetTimeFrame(OldTF);
  3657.  
  3658.   return rVal;
  3659. }
  3660.  
  3661. CLTimeSpan CLDate::operator-(CLDate& ld)
  3662. {
  3663.   AssertValid();
  3664.   ld.AssertValid();
  3665.  
  3666.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3667.   TimeFrame OldTF1 = GetTimeFrame();
  3668.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3669.  
  3670.   BOOL bTimeFrameChangeRequired = ( (OldTF1 == LOCAL) && (OldTF2 != LOCAL) ||
  3671.                                     (OldTF1 != LOCAL) && (OldTF2 == LOCAL) );
  3672.   if (bTimeFrameChangeRequired)
  3673.   {
  3674.     TimeFrame OldTF1 = SetTimeFrame(UCT);
  3675.     TimeFrame OldTF2 = ld.SetTimeFrame(UCT);
  3676.   }
  3677.  
  3678.   __int64 s = m_nSeconds - ld.m_nSeconds;
  3679.   CLTimeSpan rVal(s);
  3680.  
  3681.   SetTimeFrame(OldTF1);
  3682.   ld.SetTimeFrame(OldTF2);
  3683.  
  3684.   return rVal;
  3685. }
  3686.  
  3687. CLDate CLDate::operator-(const CLTimeSpan& TimeSpan)
  3688. {
  3689.   AssertValid();
  3690.   TimeSpan.AssertValid();
  3691.  
  3692.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3693.   TimeFrame OldTF = GetTimeFrame();
  3694.   if (GetTimeFrame() == LOCAL)
  3695.     SetTimeFrame(UCT);
  3696.  
  3697.   __int64 s = m_nSeconds - TimeSpan.m_nSeconds;
  3698.   CLDate rVal;
  3699.   rVal.m_nSeconds = s;
  3700.   rVal.m_TimeFrame = m_TimeFrame;
  3701.   rVal.m_bValid = TRUE;
  3702.  
  3703.   SetTimeFrame(OldTF);
  3704.  
  3705.   return rVal;
  3706. }
  3707.  
  3708. CLDate& CLDate::operator+=(const CLTimeSpan& TimeSpan)
  3709. {
  3710.   *this = *this + TimeSpan;
  3711.   return *this;
  3712. }
  3713.  
  3714. CLDate& CLDate::operator-=(const CLTimeSpan& TimeSpan)
  3715. {
  3716.   *this = *this - TimeSpan;
  3717.   return *this;
  3718. }
  3719.  
  3720. CLDate& CLDate::operator++()
  3721. {
  3722.   AssertValid();
  3723.   m_nSeconds += 86400;
  3724.   return *this;
  3725. }
  3726.  
  3727. CLDate& CLDate::operator--()
  3728. {
  3729.   AssertValid();
  3730.   m_nSeconds -= 86400;
  3731.   return *this;
  3732. }
  3733.   
  3734. BOOL CLDate::operator==(CLDate& ld)
  3735. {
  3736.   AssertValid();
  3737.   
  3738.   //Match the two instances timeframes if neccessary
  3739.   TimeFrame OldTF1 = GetTimeFrame();
  3740.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3741.  
  3742.   BOOL bTimeFrameChangeRequired = (OldTF1 != OldTF2);
  3743.   if (bTimeFrameChangeRequired)
  3744.   {
  3745.     TimeFrame OldTF1 = SetTimeFrame(UCT);
  3746.     TimeFrame OldTF2 = ld.SetTimeFrame(UCT);
  3747.   }
  3748.  
  3749.   BOOL rVal = (m_nSeconds == ld.m_nSeconds);
  3750.  
  3751.   SetTimeFrame(OldTF1);
  3752.   ld.SetTimeFrame(OldTF2);
  3753.  
  3754.   return rVal;
  3755. }
  3756.  
  3757. BOOL CLDate::operator>(CLDate& ld)
  3758. {
  3759.   AssertValid();
  3760.  
  3761.   //Match the two instances timeframes if neccessary
  3762.   TimeFrame OldTF1 = GetTimeFrame();
  3763.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3764.   BOOL bTimeFrameChangeRequired = (OldTF1 != OldTF2);
  3765.   if (bTimeFrameChangeRequired)
  3766.   {
  3767.     TimeFrame OldTF1 = SetTimeFrame(UCT);
  3768.     TimeFrame OldTF2 = ld.SetTimeFrame(UCT);
  3769.   }
  3770.  
  3771.   BOOL rVal = (m_nSeconds > ld.m_nSeconds);
  3772.  
  3773.   SetTimeFrame(OldTF1);
  3774.   ld.SetTimeFrame(OldTF2);
  3775.  
  3776.   return rVal;
  3777. }
  3778.  
  3779. BOOL CLDate::operator>=(CLDate& ld)
  3780. {
  3781.   AssertValid();
  3782.  
  3783.   //Match the two instances timeframes if neccessary
  3784.   TimeFrame OldTF1 = GetTimeFrame();
  3785.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3786.   BOOL bTimeFrameChangeRequired = (OldTF1 != OldTF2);
  3787.   if (bTimeFrameChangeRequired)
  3788.   {
  3789.     TimeFrame OldTF1 = SetTimeFrame(UCT);
  3790.     TimeFrame OldTF2 = ld.SetTimeFrame(UCT);
  3791.   }
  3792.  
  3793.   BOOL rVal = (m_nSeconds >= ld.m_nSeconds);
  3794.  
  3795.   SetTimeFrame(OldTF1);
  3796.   ld.SetTimeFrame(OldTF2);
  3797.  
  3798.   return rVal;
  3799. }
  3800.  
  3801. BOOL CLDate::operator<(CLDate& ld)
  3802. {
  3803.   AssertValid();
  3804.  
  3805.   //Match the two instances timeframes if neccessary
  3806.   TimeFrame OldTF1 = GetTimeFrame();
  3807.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3808.   BOOL bTimeFrameChangeRequired = (OldTF1 != OldTF2);
  3809.   if (bTimeFrameChangeRequired)
  3810.   {
  3811.     TimeFrame OldTF1 = SetTimeFrame(UCT);
  3812.     TimeFrame OldTF2 = ld.SetTimeFrame(UCT);
  3813.   }
  3814.  
  3815.   BOOL rVal = (m_nSeconds < ld.m_nSeconds);
  3816.  
  3817.   SetTimeFrame(OldTF1);
  3818.   ld.SetTimeFrame(OldTF2);
  3819.  
  3820.   return rVal;
  3821. }
  3822.  
  3823. BOOL CLDate::operator<=(CLDate& ld)
  3824. {
  3825.   AssertValid();
  3826.  
  3827.   //Match the two instances timeframes if neccessary
  3828.   TimeFrame OldTF1 = GetTimeFrame();
  3829.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3830.   BOOL bTimeFrameChangeRequired = (OldTF1 != OldTF2);
  3831.   if (bTimeFrameChangeRequired)
  3832.   {
  3833.     TimeFrame OldTF1 = SetTimeFrame(UCT);
  3834.     TimeFrame OldTF2 = ld.SetTimeFrame(UCT);
  3835.   }
  3836.  
  3837.   BOOL rVal = (m_nSeconds <= ld.m_nSeconds);
  3838.  
  3839.   SetTimeFrame(OldTF1);
  3840.   ld.SetTimeFrame(OldTF2);
  3841.  
  3842.   return rVal;
  3843. }
  3844.  
  3845. BOOL CLDate::operator!=(CLDate& ld)
  3846. {
  3847.   AssertValid();
  3848.   return !operator==(ld);
  3849. }
  3850.  
  3851. #ifdef _DEBUG
  3852. void CLDate::AssertValid() const       
  3853. {
  3854.   CObject::AssertValid();
  3855.   ASSERT(IsValid());
  3856. }
  3857. #endif
  3858.  
  3859. #ifdef _DEBUG
  3860. void CLDate::Dump(CDumpContext& dc) const
  3861. {
  3862.   CObject::Dump(dc);
  3863.   if (IsValid())
  3864.     dc << Format() << _T("\n");
  3865.   else
  3866.     dc << _T("Invalid state\n");
  3867. }
  3868. #endif           
  3869.  
  3870. /*
  3871. CString CLDate::Format(const CString& sFormat=CDate::m_sDefaultFormat) const
  3872. %a    Abbreviated weekday name
  3873. %A    Full weekday name
  3874. %b    Abbreviated month name
  3875. %B    Full month name
  3876. %d    Day of month as decimal number (01 - 31)
  3877. %j    Day of year as decimal number (001 - 366)
  3878. %m    Month as decimal number (01 - 12)
  3879. %P    AM / PM indicator
  3880. %U    Week of year as decimal number
  3881. %w    Weekday as decimal number (1 - 7; Sunday is 1)
  3882. %x    Date representation for current locale,  namely 
  3883.         Date representation + " " + Time Representation for current locale
  3884. %y    Year without century, as decimal number (00 - 99)
  3885. %Y    Year with century, as decimal number
  3886. %c    Year displayed using C.E.(Current Epoch) / B.C.E (Before Current Epoch) convention e.g. -1023 = 1022 BCE
  3887. %t    String containing a representation of the TimeFrame ("UCT", "LOCAL" or "ET")
  3888.  
  3889. %H    Hours in the day
  3890. %h    12 Hour format Hours in (00 - 12)
  3891. %M    Minutes in the hour
  3892. %S    Seconds in the minute
  3893. %F    MilliSeconds in the second
  3894. %%    Percent sign        
  3895.  
  3896.  
  3897. //may also need to include full windows escape character
  3898.  
  3899. %%    Percent sign
  3900.  
  3901. As in the printf function, the # flag may prefix any formatting code. 
  3902. In that case, the meaning of the format code is changed as follows.
  3903.  
  3904. Format Code Meaning
  3905. %#x Long date representation, appropriate to current locale, namely
  3906.       Long Date representation + " " + Time Representation for current locale
  3907.  
  3908.  
  3909. %#d, %#j, %#m, %#U, %#w, %#y, %#H, %#h, %#M, %#S  Remove leading zeros (if any).
  3910. */
  3911. CString CLDate::Format(const CString& sFormat) const
  3912.   CString rVal;
  3913.   if (IsValid())
  3914.   {
  3915.     CString sBuffer;
  3916.     int sFmtLength = sFormat.GetLength();
  3917.  
  3918.     for (int i=0; i<sFmtLength; i++)
  3919.     {
  3920.       TCHAR c = sFormat.GetAt(i);
  3921.       if (c == '%')
  3922.       {
  3923.         ++i;
  3924.         if (i < sFmtLength)
  3925.         {
  3926.           c = sFormat.GetAt(i);
  3927.           switch (c)
  3928.           {
  3929.             case _T('H'):
  3930.             {
  3931.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetHour());
  3932.               rVal += sBuffer;
  3933.               break;
  3934.             }
  3935.             case _T('h'):
  3936.             {
  3937.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetAMPMHour());
  3938.               rVal += sBuffer;
  3939.               break;
  3940.             }
  3941.             case _T('M'):
  3942.             {
  3943.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetMinute());
  3944.               rVal += sBuffer;
  3945.               break;
  3946.             }
  3947.             case _T('P'):
  3948.             {
  3949.               rVal += GetCLTimeOfDay().GetAMPMString();
  3950.               break;
  3951.             }
  3952.             case _T('S'):
  3953.             {
  3954.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetSecond());
  3955.               rVal += sBuffer;
  3956.               break;
  3957.             }
  3958.             case _T('a'):
  3959.             {
  3960.               rVal += GetCDate().GetAbrStringDayOfWeek();
  3961.               break;
  3962.             }
  3963.             case _T('A'):
  3964.             {
  3965.               rVal += GetCDate().GetFullStringDayOfWeek();
  3966.               break;
  3967.             }
  3968.             case _T('b'):
  3969.             {
  3970.               rVal += GetCDate().GetAbrStringMonth();
  3971.               break;
  3972.             }
  3973.             case _T('B'):
  3974.             {
  3975.               rVal += GetCDate().GetFullStringMonth();
  3976.               break;
  3977.             }
  3978.             case _T('c'):
  3979.             {
  3980.               rVal += GetCDate().GetStringCEBCEYear();
  3981.               break;
  3982.             }
  3983.             case _T('d'):
  3984.             {
  3985.               sBuffer.Format(_T("%.02d"), GetCDate().GetDay());
  3986.               rVal += sBuffer;
  3987.               break;
  3988.             }
  3989.             case _T('j'):
  3990.             {
  3991.               sBuffer.Format(_T("%.03d"), GetCDate().DaysSinceJan0());
  3992.               rVal += sBuffer;
  3993.               break;
  3994.             }
  3995.             case _T('m'):
  3996.             {
  3997.               sBuffer.Format(_T("%.02d"), GetCDate().GetMonth());
  3998.               rVal += sBuffer;
  3999.               break;
  4000.             }
  4001.             case _T('t'):
  4002.             {
  4003.               rVal += GetStringTimeFrame();
  4004.               break;
  4005.             }
  4006.             case _T('U'):
  4007.             {
  4008.               sBuffer.Format(_T("%.02d"), GetCDate().GetWeekOfYear());
  4009.               rVal += sBuffer;
  4010.               break;
  4011.             }
  4012.             case _T('w'):
  4013.             {
  4014.               sBuffer.Format(_T("%d"), GetCDate().GetDayOfWeek());
  4015.               rVal += sBuffer;
  4016.               break;
  4017.             }
  4018.             case _T('x'):
  4019.             {
  4020.               rVal += GetCDate().Format(_T("%x")) + _T(" ") + GetCLTimeOfDay().Format(_T("%x"));
  4021.               break;
  4022.             }
  4023.             case _T('y'):
  4024.             {
  4025.               LONG Year = GetCDate().GetYear();
  4026.               sBuffer.Format(_T("%.02d"), GetCDate().Get2DigitYear());
  4027.               rVal += sBuffer;
  4028.               break;
  4029.             }
  4030.             case _T('Y'):
  4031.             {
  4032.               sBuffer.Format(_T("%ld"), GetCDate().GetYear());
  4033.               rVal += sBuffer;
  4034.               break;
  4035.             }
  4036.             case _T('#'):
  4037.             {
  4038.               if (i < sFmtLength)
  4039.               {
  4040.                 ++i;
  4041.                 c = sFormat.GetAt(i);
  4042.                 switch (c)
  4043.                 {
  4044.                   case _T('d'):
  4045.                   {
  4046.                     sBuffer.Format(_T("%d"), GetCDate().GetDay());
  4047.                     rVal += sBuffer;
  4048.                     break;
  4049.                   }
  4050.                   case _T('j'):
  4051.                   {
  4052.                     sBuffer.Format(_T("%d"), GetCDate().DaysSinceJan0());
  4053.                     rVal += sBuffer;
  4054.                     break;
  4055.                   }
  4056.                   case _T('m'):
  4057.                   {
  4058.                     sBuffer.Format(_T("%d"), GetCDate().GetMonth());
  4059.                     rVal += sBuffer;
  4060.                     break;
  4061.                   }
  4062.                   case _T('U'):
  4063.                   {
  4064.                     sBuffer.Format(_T("%d"), GetCDate().GetWeekOfYear());
  4065.                     rVal += sBuffer;
  4066.                     break;
  4067.                   }
  4068.                   case _T('x'):
  4069.                   {
  4070.                     rVal += GetCDate().Format(_T("%#x")) + _T(" ") + GetCLTimeOfDay().Format(_T("%x"));
  4071.                     break;
  4072.                   }
  4073.                   case _T('y'):
  4074.                   {
  4075.                     LONG Year = GetCDate().GetYear();
  4076.                     sBuffer.Format(_T("%d"), GetCDate().Get2DigitYear());
  4077.                     rVal += sBuffer;
  4078.                     break;
  4079.                   }
  4080.                   case _T('H'):
  4081.                   {
  4082.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetHour());
  4083.                     rVal += sBuffer;
  4084.                     break;
  4085.                   }
  4086.                   case _T('h'):
  4087.                   {
  4088.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetAMPMHour());
  4089.                     rVal += sBuffer;
  4090.                     break;
  4091.                   }
  4092.                   case _T('M'):
  4093.                   {
  4094.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetMinute());
  4095.                     rVal += sBuffer;
  4096.                     break;
  4097.                   }
  4098.                   case _T('S'):
  4099.                   {
  4100.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetSecond());
  4101.                     rVal += sBuffer;
  4102.                     break;
  4103.                   }
  4104.                   default:
  4105.                   {
  4106.                     rVal += c;
  4107.                     break;
  4108.                   }
  4109.                 }
  4110.               }
  4111.               break;
  4112.             }
  4113.             default:
  4114.             {
  4115.               rVal += c;
  4116.               break;
  4117.             }
  4118.           }
  4119.         }
  4120.       }
  4121.       else
  4122.       {
  4123.         rVal += c;
  4124.       }
  4125.     }
  4126.   }
  4127.  
  4128.   return rVal;
  4129. }
  4130.  
  4131. //Format according to the short date and time format as specified by the control panel
  4132. CString CLDate::Format(DWORD dwFlags) const
  4133. {
  4134.   //let the component parts of the long date handle their formatting
  4135.   CDate Date = GetCDate();
  4136.   CLTimeOfDay Tod = GetCLTimeOfDay();
  4137.  
  4138.   if (dwFlags & DTF_NOTIMEFRAME)
  4139.     return Date.Format() + _T(" ") + Tod.Format(dwFlags);
  4140.   else
  4141.     return Date.Format() + _T(" ") + Tod.Format(dwFlags) + _T(" ") + Format(_T("%t"));
  4142. }
  4143.  
  4144. void CLDate::Serialize(CArchive& ar)
  4145. {
  4146.   CObject::Serialize(ar);
  4147.  
  4148.   if (ar.IsStoring())
  4149.   {
  4150.     ar << m_nSeconds;
  4151.     ar << (WORD) m_TimeFrame;
  4152.     ar << m_bValid;
  4153.   }
  4154.   else
  4155.   {
  4156.     ar >> m_nSeconds;
  4157.     ar >> (WORD&) m_TimeFrame;
  4158.     ar >> m_bValid;
  4159.   }
  4160. }
  4161.  
  4162. ostream& operator<<(ostream& os, const CLDate& ld)
  4163. {
  4164.   return os << ld.Format();
  4165. }
  4166.  
  4167. CArchive& operator<<(CArchive& ar, CLDate& ld)
  4168. {
  4169.   ASSERT(ar.IsStoring());
  4170.   ld.Serialize(ar);
  4171.   return ar;
  4172. }
  4173.  
  4174. CArchive& operator>>(CArchive& ar, CLDate& ld)
  4175. {
  4176.   ASSERT(!ar.IsStoring());
  4177.   ld.Serialize(ar);
  4178.   return ar;
  4179. }
  4180.  
  4181.  
  4182.  
  4183.